java - Neo4j java遍历api对象映射

标签 java neo4j spring-data-neo4j

我正在尝试将 TraversalDescription.traverse() 的结果映射到自定义节点和关系对象的列表。

如果我将 Cypher 与 sdn 一起使用,我可以执行以下操作:

@Query("WITH {0} AS ns, {1} AS ne " +
    "MATCH p=(n1{name:ns})-[*]-(n), (n2{name:ne}) " +
    "WHERE n=n2 " +
    "AND all(a IN nodes(p) WHERE single(x IN nodes(p) WHERE x=a)) " +
    "RETURN nodes(p) as persons, rels(p) as connections " +
    "ORDER BY size(nodes(p))")
List<GraphPath> getAllPaths(String startNode, String endNode);

然后映射到包含自定义节点和关系对象的 GraphPath 对象:

图形路径.java

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@QueryResult
public class GraphPath {    
    private List<Person> persons;
    private List<Connection> connections;    
}

Person.java

@Getter
@Setter
@NoArgsConstructor
@NodeEntity(label = "Person")
public class Person extends Entity{

    @Property(name = "name")
    private String fullName;

    @Property(name = "status")
    private String status;

    @Relationship(type = "CONNECTS", direction = Relationship.UNDIRECTED)
    private Set<Connection> personConnections = new HashSet<>();
}

连接.java

@Getter
@Setter
@NoArgsConstructor
@RelationshipEntity(type = "CONNECTS")
public class Connection extends Entity{

    @Property(name="connection_id")
    private String connectId;

    @Property(name = "status")
    private String status;

    @StartNode
    private Person personSource;

    @EndNode
    private Person personTarget;
}

而 Entity.java 只是具有字段 id 和覆盖的 equals() 和 hashCode() 的 POJO

这在简单的图形中运行良好,但当图形变得更复杂时,获得结果的时间会增加更多。我的目标是找到起始节点和结束节点之间的所有可能路径,并且每条路径中没有重复的节点或关系。我希望使用遍历 API 来消除运行中一些不需要的路径(包含重复节点或关系的路径),以减少处理时间。

这是我使用的代码,graphDb 只是 GraphDatabaseService:

final Node startNode = graphDb.findNode(Labels.Person, "name", startNodeName);
final Node endNode = graphDb.findNode(Labels.Person, "name", endNodeName);
TraversalDescription td = graphDb.traversalDescription()
        .depthFirst()
        .evaluator(Evaluators.excludeStartPosition())
        .evaluator(Evaluators.includeWhereEndNodeIs(endNode))
        .relationships(Types.CONNECTS)
                .uniqueness(Uniqueness.NODE_PATH)
                .uniqueness(Uniqueness.RELATIONSHIP_PATH);
Traverser t = td.traverse(startNode)  

现在的问题是,我怎样才能将结果映射到我上面提到的自定义对象?手动执行会导致我必须处理递归对象映射( Person 中的 Connection,以及 Connection 中的目标和源 Person)。

最佳答案

正如我在评论中所写,我想我会手动进行映射,因为 Traverser 返回的 Path 已经包含节点和关系,并且只有现在需要读取属性。

通过在 Path 上迭代,可以构建 GraphPath 及其 PersonConnection依次完成。这段代码显然可以通过提取方法进行重构。

for (Path path : t) {
    GraphPath gp = new GraphPath();
    Person person = null;
    Connection connection = null;

    for (PropertyContainer pc : path) {
        if (pc instanceof Node) {
            Node node = (Node) pc;

            person = new Person();
            person.setId(node.getId());
            person.setFullName(node.getProperty("name", null));
            person.setStatus(node.getProperty("status", null));
            gp.getPersons().add(person);

            // No connection exists for the first node in the path
            if (connection != null) {
                // Find out which end has already been connected
                if (connection.getPersonSource() == null) {
                    connection.setPersonSource(person);
                } else {
                    connection.setPersonTarget(person);
                }
                person.getPersonConnections().add(connection);
            }
        } else {
            Relationship rel = (Relationship) pc;

            connection = new Connection();
            connection.setId(rel.getId());
            connection.setConnectId(rel.getProperty("connection_id", null));
            connection.setStatus(rel.getProperty("status", null));
            gp.getConnections().add(connection);

            // Find out which end has already been mapped
            if (rel.getStartNode().getId() == person.getId().longValue()) {
                connection.setPersonSource(person);
            } else {
                connection.setPersonTarget(person);
            }
            person.getPersonConnections().add(connection);
        }
    }
}

如果您想要给定节点的单个Person(resp. Connection)实例,您可以更改Person(resp. Connection) 创建以首先查找 Map,您将在其中按 id 索引实体;您还必须一起更改 PersonConnection 的接线,以仅在 Connection 上设置未设置的端点,而不依赖于一端或另一端仍然无效的事实。

关于java - Neo4j java遍历api对象映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38341546/

相关文章:

properties - Neo4j中的Label和Property有什么区别?

mongodb - 在单个应用程序中使用多种数据库类型对数据建模

python - 使用 Python 在 Neo4j 中执行批量添加/插入的最快方法?

java - 如何使用SDN仅在节点不存在时创建节点?

java - Spring-Data-Neo4j:无法使用 neo4jtempalte createRelationshipBetween)() 方法创建实体之间的关系

java - 使用涉及每个元素索引的计算在数组中赋值

java - 使用 Ivy/ant 从命令行将符号名称解析为版本号?

java - 为 Neo4j 节点实体生成分层数据

java - 我如何在类中包含(常量)原始数据表?

java - @all 在 JSF Ajax 中不起作用