neo4j - 使用 Neo4j/Cypher 查找选定子图的所有叶子
问题描述
初始情况
- 具有树状结构的大型 Neo4j 3.4.6 图(10 层深,1000 万个节点)。
- 毫无例外,所有节点都相互连接。节点和关系在每种情况下都属于同一类型。
- 正好是一个中心根节点。
- 简化和简化的示例:
CREATE (Root:CustomType {name: 'Root'})
CREATE (NodeA:CustomType {name: 'NodeA'})
CREATE (NodeB:CustomType {name: 'NodeB'})
CREATE (NodeC:CustomType {name: 'NodeC'})
CREATE (NodeD:CustomType {name: 'NodeD'})
CREATE (NodeE:CustomType {name: 'NodeE'})
CREATE (NodeF:CustomType {name: 'NodeF'})
CREATE (NodeG:CustomType {name: 'NodeG'})
CREATE (NodeH:CustomType {name: 'NodeH'})
CREATE (NodeI:CustomType {name: 'NodeI'})
CREATE (NodeJ:CustomType {name: 'NodeJ'})
CREATE (NodeK:CustomType {name: 'NodeK'})
CREATE (NodeL:CustomType {name: 'NodeL'})
CREATE (NodeM:CustomType {name: 'NodeM'})
CREATE (NodeN:CustomType {name: 'NodeN'})
CREATE (NodeO:CustomType {name: 'NodeO'})
CREATE (NodeP:CustomType {name: 'NodeP'})
CREATE (NodeQ:CustomType {name: 'NodeQ'})
CREATE
(Root)-[:CONTAINS]->(NodeA),
(Root)-[:CONTAINS]->(NodeB),
(Root)-[:CONTAINS]->(NodeC),
(NodeA)-[:CONTAINS]->(NodeD),
(NodeA)-[:CONTAINS]->(NodeE),
(NodeA)-[:CONTAINS]->(NodeF),
(NodeE)-[:CONTAINS]->(NodeG),
(NodeE)-[:CONTAINS]->(NodeH),
(NodeF)-[:CONTAINS]->(NodeI),
(NodeF)-[:CONTAINS]->(NodeJ),
(NodeF)-[:CONTAINS]->(NodeK),
(NodeI)-[:CONTAINS]->(NodeL),
(NodeI)-[:CONTAINS]->(NodeM),
(NodeJ)-[:CONTAINS]->(NodeN),
(NodeK)-[:CONTAINS]->(NodeO),
(NodeK)-[:CONTAINS]->(NodeP),
(NodeM)-[:CONTAINS]->(NodeQ);
待解决的挑战
- 通过 MATCH-WITH-UNWIND Cypher 查询,我可以成功选择子树并将其绑定到路径。假设子树跨越节点 A、E、F、I 和 J。
- 基于这条路径,我现在需要子树的所有叶子,而不是完整的树。
.
MATCH
path = (:CustomType {name:'NodeA'})-[:CONTAINS*]->(:CustomType {name:'NodeJ'}) /* simplified */
WITH
nodes(path) as selectedPath
/* here: necessary magic to identify the leaf nodes of the subtree */
RETURN
leafNode;
- 除其他外,我尝试用一种
WHERE NOT(node-->())
方法解决需求,但意识到这仅适用于完整树的叶子。不幸的是,我无法说服该WHERE NOT(node-->())
子句尊重选定的子树边界。 - 那么,如何使用 Cypher 和 Neo4j 找到选定子图的所有叶子?你能给我一个建议如何解决这个挑战吗?非常感谢您为我指明了正确的方向!
解决方案
您正确地注意到没有子节点的检查节点仅适用于整个树。所以你需要遍历子树中的所有关系,找到子树的这样一个节点作为关系的结束,而不是关系的开始:
MATCH
path = (:CustomType {name:'NodeA'})-[:CONTAINS*]->(:CustomType {name:'NodeJ'})
UNWIND relationShips(path) AS r
WITH collect(DISTINCT endNode(r)) AS endNodes,
collect(DISTINCT startNode(r)) AS startNodes
UNWIND endNodes AS leaf
WITH leaf WHERE NOT leaf IN startNodes
RETURN leaf
推荐阅读
- mongodb - MongoDB 聚合:将每个数组值从另一个字段添加到数组内的每个对象。合并/合并来自不同字段的两个数组
- vb.net - VB Express 2010 找不到我不想再找的文件
- nginx - 通过本地网络访问 nginx 服务器上的子域
- html - 如何在 Swift 中将 NSAttributed 单词加粗?
- javascript - Javascript TypeError:无法读取未定义的属性“1”
- python - 如何在 Python 中处理损坏的管道?
- python - 多个表单在页面上的每个表单都有特定的 Flask Flash 消息
- reactjs - 如何使用样式化组件在 React Native 中设置嵌套组件的样式
- postgresql - 真空的意义 10 天前
- django - Django 翻译返回所有辅助语言的页面未找到 (404)