首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Neo4j java遍历api对象映射

Neo4j java遍历api对象映射
EN

Stack Overflow用户
提问于 2016-07-13 02:07:23
回答 1查看 452关注 0票数 3

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

如果我在sdn中使用Cypher,我可以执行以下操作:

代码语言:javascript
复制
@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对象:

GraphPath.java

代码语言:javascript
复制
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@QueryResult
public class GraphPath {    
    private List<Person> persons;
    private List<Connection> connections;    
}

Person.java

代码语言:javascript
复制
@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<>();
}

Connection.java

代码语言:javascript
复制
@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字段的POJO,覆盖了等于()和hashCode()

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

下面是我使用的代码,graphDb就是GraphDatabaseService:

代码语言:javascript
复制
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)  

现在的问题是,如何将结果映射到我前面提到的自定义对象?手动执行它将达到必须处理递归对象映射(亲自连接的集合,以及连接中的目标和源人员)的地步。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-19 12:25:06

正如我在注释中所写的,我认为我应该手动进行映射,因为Traverser返回的Traverser已经包含节点和关系,现在只需要读取属性。

通过在Path上迭代,可以依次构造和完成GraphPath及其Persons和Connections。显然,通过提取方法可以重构此代码。

代码语言:javascript
复制
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上的未设置结束,而不依赖于一个或另一端仍然为null的事实。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38341546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档