代码之家  ›  专栏  ›  技术社区  ›  ThanksForAllTheFish

Neo4j双向遍历api

  •  1
  • ThanksForAllTheFish  · 技术社区  · 10 年前

    我正在玩Neo4j,到目前为止,我有一个地理图 AIRPORT 连接到 CITY 这个 城市 COUNTRY 以及 国家 CONTINENT ,如图所示 enter image description here

    箭头上的标签转换为 org.neo4j.graphdb.RelationshipType 输入我的代码。到目前为止,我可以在开始节点之间构建路径 MXP 到结束节点 LTN 使用以下单向遍历。

    Traverser traverse = database.traversalDescription().depthFirst()
      .relationships(CITY, BOTH)
      .relationships(CONTINENT, BOTH)
      .relationships(COUNTRY, BOTH)
      .relationships(REGION, BOTH)
      .evaluator(Evaluators.includeWhereEndNodeIs(endNode)).traverse(startNode);
    

    有了这个,我得到了一条路 MXP -> Milan -> Italy -> Europe <- England <- London <- LTN ,这是正确的,给出了图形描述,遍历描述,当然,我理解我对这种描述的理解。

    我试图更改此代码以执行双向遍历,这意味着我希望从两者开始 MXP公司 LTN公司 并在碰撞点停止。我尝试了以下代码段,其中的注释意味着我的理解,因此可能更容易指出问题。

    TraversalDescription startSide = database.traversalDescription().depthFirst() //Depth first algorithm
      .relationships(CITY, OUTGOING) //consider CITY relationship, only outgoing
      .relationships(REGION, OUTGOING) //consider REGION relationship, only outgoing
      .relationships(COUNTRY, OUTGOING) //consider COUNTRY relationship, only outgoing
      .relationships(CONTINENT, OUTGOING) //consider CONTINENT relationship, only outgoing
      .evaluator(Evaluators.excludeStartPosition()); //do not consider the starting point. 
                                                   //Here I tried also with all, with the same result
                                                   //with includeWhereEndNodeIs(endNode), again with same result
                                                   //and combining includeWhereEndNodeIs and excludeStartPosition, once more with same result.
                                                   //All tries I mirrored for the endSide description, changing endNode to startNode where I feel it was needed
    
    TraversalDescription endSide = database.traversalDescription().depthFirst()
      .relationships(CITY, OUTGOING)
      .relationships(REGION, OUTGOING)
      .relationships(COUNTRY, OUTGOING)
      .relationships(CONTINENT, OUTGOING)
      .evaluator(Evaluators.excludeStartPosition());
    
    List<Node> asList = Arrays.asList(startNode, endNode);
    Traverser traverse = database.bidirectionalTraversalDescription().endSide(endSide).startSide(startSide).traverse(asList, asList);
    

    在这里,我得到了两条路径,一条路径只有 MXP公司 一个只有 LTN公司 .

    在这一点上,我认真地认为我完全误解了双向遍历,甚至可能误解了它的目的。我的错误在哪里?为什么我没有得到相同的输出?

    1 回复  |  直到 10 年前
        1
  •  0
  •   Community Egal    4 年前

    我终于找到了一个可行的解决方案。我的代码中的问题与 uniqueness 我问题的有趣之处是

    设置在遍历过程中如何重新访问位置的规则,如“唯一性”中所述。如果未设置,则默认值为NODE_GLOBAL。

    NODE_GLOBAL唯一性:整个图中的任何节点都不能被多次访问。这可能会消耗大量内存,因为它需要保持内存中的数据结构来记住所有访问的节点。

    NODE_PATH唯一性:一个节点之前可能不会出现在到达它的路径中。

    这些描述与 official API 所以我尝试了不同的组合,最后得到了以下代码:

    TraversalDescription bothSide = database.traversalDescription().depthFirst()
        .relationships(CITY, OUTGOING)
        .relationships(REGION, OUTGOING)
        .relationships(COUNTRY, OUTGOING)
        .relationships(CONTINENT, OUTGOING)
        .uniqueness(NODE_PATH);
      
    Traverser traverser = database
        .bidirectionalTraversalDescription()
        .startSide(bothSide)
        .endSide(bothSide)
        .traverse(node, endNode);
    

    基本上,我定义了一个 TraversalDescription 在终点和起点,我只想跟随 OUTGOING 我只想考虑路径本身中节点唯一的路径。

    然后,我定义了 bidirectional traverser 它只需设置结束端和开始端,并从开始节点遍历图形 node 到结束节点 endNode (实际上,它同时从开始到结束和从结束到开始进行遍历,当两个遍历发生冲突时停止,将生成的路径合并为一条从 start end ).

    注释 我不完全确定 NODE_GLOBAL ,因为在我的数据库中,每个节点都表示一个地理实体,所以路径中的每个节点 MXP -> Milan -> Italy -> Europe <- England <- London <- LTN 应该只访问一次,因此 节点_全局 NODE_PATH 在此背景下。