我正在学习Neo4J。
我了解如何对节点进行深度优先搜索,但是在我的情况下,我想序列化所有节点,但要完全遍历一个分支,然后移至下一个分支,依此类推。
给出以下节点:
N1 { order: 1 }
N2 { order: 1 }
N4 { order: 1 }
N5 { order: 1 }
N6 { order: 2 }
N3 { order: 2 }
N7 { order: 1 }
节点之间的关系是名为part_of
的有向节点。 E.i. N2-[part_of]->N1
。
我希望列表按以下顺序序列化:N1 N2 N4 N5 N6 N3 N7
。
最有效的方法是什么?
先谢谢了。
// E
答案 0 :(得分:0)
您现在可能已经在Neo4j Graph Algorithms插件中发现了algo.dfs.stream
函数,该函数可以使您半途而废:
MATCH (startNode: Node { name: 'N1' } )
CALL algo.dfs.stream('Node', 'PART_OF', 'BOTH', id(startNode))
YIELD nodeIds
UNWIND nodeIds as nodeId
WITH algo.asNode(nodeId) as n
RETURN n
麻烦的是algo.dfs.stream
不允许您控制节点在兄弟姐妹之间的遍历-最好的选择可能是在应用程序代码中做到这一点,编写DFS非常简单。
但是,在过去的几个小时中,我花了很多时间研究一种纯Cypher的方法,该方法确实通过您的order
属性以稳定的顺序执行了深度优先搜索,令人发笑。出于以下几个原因,我衷心恳请您不要使用此代码:
但是不将其张贴在某个地方似乎很浪费,所以我们在这里。
假设一些测试数据与您的样品匹配:
MERGE (n1: Node { order: 1, name: 'N1' })
MERGE (n2: Node { order: 1, name: 'N2' })
MERGE (n3: Node { order: 2, name: 'N3' })
MERGE (n4: Node { order: 1, name: 'N4' })
MERGE (n5: Node { order: 1, name: 'N5' })
MERGE (n6: Node { order: 2, name: 'N6' })
MERGE (n7: Node { order: 1, name: 'N7' })
MERGE (n2)-[:PART_OF]->(n1)
MERGE (n4)-[:PART_OF]->(n2)
MERGE (n5)-[:PART_OF]->(n4)
MERGE (n6)-[:PART_OF]->(n4)
MERGE (n3)-[:PART_OF]->(n1)
MERGE (n7)-[:PART_OF]->(n3)
以下内容将产生DFS遍历,其中通过对节点的order
属性进行排序来选择同级节点。
MATCH (root: Node { name: 'N1' }), pathFromRoot=shortestPath((root)<-[:PART_OF*]-(leaf: Node)) WHERE NOT ()-[:PART_OF]->(leaf)
WITH nodes(pathFromRoot) AS pathFromRootNodes
WITH pathFromRootNodes, reduce(pathString = "", pathElement IN pathFromRootNodes | pathString + '/' + right("00000" + toString(pathElement.order), 6)) AS orderPathString ORDER BY orderPathString
WITH reduce(concatPaths = [], p IN collect(pathFromRootNodes) | concatPaths + p) AS allPaths
WITH reduce(distinctNodes = [], n IN allPaths | CASE WHEN n IN distinctNodes THEN distinctNodes ELSE distinctNodes + n end) AS traversalOrder
RETURN [x in traversalOrder | x.name]
我不会逐行解释,但要旨是:
order
属性组合在一起,使得通过此键对路径进行排序可以得出到达每个叶节点的顺序