[英]Neo4j bidirectional traversal api
我正在玩Neo4j,到目前为止,我有一个地理图,其中AIRPORT
连接到CITY
, CITY
连接到COUNTRY
, COUNTRY
到CONTINENT
,如图所示
箭头上的标签将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
。
在这一点上,我深信我完全误解了双向遍历,甚至可能是它的目的。 我的错误在哪里? 为什么我没有得到相同的输出?
我终于有了一个可行的解决方案。 我的代码中的问题与唯一性的概念有关。 我的问题有趣的一点是
设置规则,以便在遍历期间重新访问位置,如“唯一性”中所述。 如果未设置,则默认为NODE_GLOBAL。
NODE_GLOBAL唯一性:整个图形中的任何节点都不能被多次访问。 这可能会消耗大量内存,因为它需要保持内存中的数据结构来记住所有访问的节点。
NODE_PATH唯一性:节点可能不会在到达它的路径中先前出现。
这些描述与官方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
,在这里我只想遵循传出关系,并且我只想考虑路径本身在节点内唯一的路径。
然后,我定义了一个bidirectional traverser
,该bidirectional traverser
器简单地设置了端点和起始端,并从起始节点node
到终止节点endNode
遍历了图形(实际上,它从起点到终点以及从终点到起点同时遍历并在两个遍历发生冲突时停止,从而将生成的路径合并为从start
到end
的单个路径)。
注意 :我不确定NODE_GLOBAL
的含义,因为在我的数据库中,每个节点都代表一个地理实体,因此路径MXP -> Milan -> Italy -> Europe <- England <- London <- LTN
NODE_GLOBAL
MXP -> Milan -> Italy -> Europe <- England <- London <- LTN
NODE_GLOBAL
只能被访问一次,因此在这种情况下NODE_GLOBAL
和NODE_PATH
之间应该没有区别。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.