如何在Neo4j Cypher查询中返回无笛卡尔积的非重复表格结果
结论:该需求完全可以实现
你原查询产生笛卡尔积的原因是多个独立MATCH子句会将各自的匹配结果做全量交叉组合,我们可以通过先聚合收集同类型关联节点、再按索引对齐补空的方式得到你期望的结果。
实现代码
MATCH (x) WHERE x.name = "X" // 分别收集三类关联节点的名称列表,避免笛卡尔积 OPTIONAL MATCH (x)-[:A]->(a) WITH x, collect(a.name) AS aList OPTIONAL MATCH (x)<-[:B]-(b) WITH x, aList, collect(b.name) AS bList OPTIONAL MATCH (x)-[:C]-(c) WITH aList, bList, collect(c.name) AS cList // 计算三个列表的最大长度,作为最终返回的行数 WITH aList, bList, cList, reduce(maxLen = 0, len IN [size(aList), size(bList), size(cList)] | CASE WHEN len > maxLen THEN len ELSE maxLen END) AS maxLen // 按索引逐行生成结果 UNWIND range(0, maxLen - 1) AS idx RETURN CASE WHEN idx < size(aList) THEN aList[idx] ELSE null END AS `a.name`, CASE WHEN idx < size(bList) THEN bList[idx] ELSE null END AS `b.name`, CASE WHEN idx < size(cList) THEN cList[idx] ELSE null END AS `c.name`
逻辑说明
- 先单独定位节点
x,之后用OPTIONAL MATCH分别匹配三类关联节点,通过collect函数把同类型节点的名称聚合成列表,整个过程只有1行数据传递,不会产生笛卡尔积 - 计算三个列表的最大长度,作为最终返回的行数(你的示例里三个列表长度分别为3、2、1,最大长度是3,刚好对应你要的3行结果)
- 用
UNWIND展开索引序列,逐行取对应索引的列表值,超出列表长度的位置返回空值,最终结果和你期望的表格完全一致
内容的提问来源于stack exchange,提问作者Ooker
相关产品推荐
相关产品推荐

