Cypher查询如何获取路径含初始节点的所有关联mop节点 无需重复写OPTIONAL MATCH
Cypher重复OPTIONAL MATCH优化方案
核心逻辑:将需要匹配相同关系/模式的多个节点合并为同一个节点集合,仅对集合写一次匹配逻辑即可,无需为不同节点重复编写相同的匹配语句。
通用兼容方案(支持所有Neo4j版本)
该方案适合有大量同类匹配规则的场景,哪怕你有6-7种不同的关系需要匹配,也只需要写一遍规则:
MATCH p=(pInit:part{_id:'XXXXXXXXXX'})-[cons:consumes*]->(items:part) // 收集所有需要匹配关联关系的节点:路径上的items + 初始节点pInit WITH p, pInit, collect(DISTINCT items) AS itemList WITH p, pInit, itemList + [pInit] AS allTargetNodes // 展开为单个节点变量 UNWIND allTargetNodes AS targetNode // 以下所有匹配规则仅需写一次,自动覆盖items和pInit OPTIONAL MATCH (targetNode)-[relmop:isMaintainedWithOp]->(mop:maintenanceOps) // 你其他的6-7条OPTIONAL MATCH都可以写在这里,只需要写一遍 // OPTIONAL MATCH (targetNode)-[relxxx:xxx]->(xxx:xxx) // 按需聚合结果,避免结果行爆炸 WITH p, pInit, collect(CASE WHEN targetNode = pInit THEN {mopRel: relmop, mop: mop} ELSE null END) AS pInitRelations, collect(CASE WHEN targetNode <> pInit THEN {item: targetNode, mopRel: relmop, mop: mop} ELSE null END) AS itemRelations RETURN p, pInit, pInitRelations, itemRelations ORDER BY [node IN nodes(p) | node._sequence]
说明:通过CASE判断可以轻松区分匹配到的关系属于pInit还是路径上的item,不会混淆返回结果。
Neo4j 5+ 简化方案(模式理解式)
如果使用Neo4j 5及以上版本,可以用模式理解式进一步简化代码,不需要UNWIND操作:
MATCH p=(pInit:part{_id:'XXXXXXXXXX'})-[cons:consumes*]->(items:part) WITH p, pInit, items, // 匹配items的mop关系 [(items)-[relmop:isMaintainedWithOp]->(mop:maintenanceOps) | {rel: relmop, node: mop}] AS itemMops, // 匹配pInit的mop关系 [(pInit)-[relmop:isMaintainedWithOp]->(mop:maintenanceOps) | {rel: relmop, node: mop}] AS pInitMops // 其他关系也可以按同样格式追加,每种关系仅需写两行,比重复写OPTIONAL MATCH简洁很多 RETURN p, pInit, items, itemMops, pInitMops ORDER BY items._sequence
内容的提问来源于stack exchange,提问作者Yoann Maingon
相关产品推荐
相关产品推荐

