Neo4j多MATCH语句返回重复值问题求助
现有总计6个节点,分为time1和time2两个标签,每个标签下各3个节点。执行:
match (a:time1) return collect(a)
可得到预期的3个time1节点列表;但执行:
match (a:time1), (b:time2) return collect(a), collect(b)
时,预期得到各含3个元素的两个列表,实际却得到各含9个元素且每个元素重复3次的列表,输出CSV内容如下:
collect(a),collect(b)
"[(:time1 {con1: 0.9,con2: 0.0,con3: 0.0}), (:time1 {con1: 0.9,con2: 0.0,con3: 0.0}), (:time1 {con1: 0.9,con2: 0.0,con3: 0.0}), (:time1 {con1: 0.0,con2: 0.4,con3: 0.0}), (:time1 {con1: 0.0,con2: 0.4,con3: 0.0}), (:time1 {con1: 0.0,con2: 0.4,con3: 0.0}), (:time1 {con1: 0.0,con2: 0.0,con3: 0.5}), (:time1 {con1: 0.0,con2: 0.0,con3: 0.5}), (:time1 {con1: 0.0,con2: 0.0,con3: 0.5})]","[(:time2 {con1: 0.9,con2: 0.0,con3: 0.0}), (:time2 {con1: 0.0,con2: 0.4,con3: 0.0}), (:time2 {con1: 0.0,con2: 0.0,con3: 0.5}), (:time2 {con1: 0.9,con2: 0.0,con3: 0.0}), (:time2 {con1: 0.0,con2: 0.4,con3: 0.0}), (:time2 {con1: 0.0,con2: 0.0,con3: 0.5}), (:time2 {con1: 0.9,con2: 0.0,con3: 0.0}), (:time2 {con1: 0.0,con2: 0.4,con3: 0.0}), (:time2 {con1: 0.0,con2: 0.0,con3: 0.5})]"
原因分析与解决方案
原因分析
MATCH (a:time1), (b:time2)会生成笛卡尔积——每个time1节点会和每个time2节点配对,3个time1×3个time2=9条结果行。当你用collect(a)和collect(b)时,会把这9行里的所有a和b分别收集起来,所以每个time1节点会重复3次(对应3个time2节点的配对),每个time2节点也会重复3次,最终得到各含9个元素的列表。
解决方案
要避免笛卡尔积,分别收集两个标签的节点即可,推荐以下几种写法:
方法1:分步骤收集(高效推荐)
先用WITH收集其中一个标签的节点,再收集另一个,从根源避免笛卡尔积:
MATCH (a:time1) WITH collect(a) AS time1Nodes MATCH (b:time2) RETURN time1Nodes, collect(b) AS time2Nodes
方法2:使用DISTINCT去重
如果一定要在同一个MATCH中编写,可在collect中加入DISTINCT去重,但这种方法仍会先生成笛卡尔积再去重,数据量大时效率较低:
MATCH (a:time1), (b:time2) RETURN collect(DISTINCT a) AS time1Nodes, collect(DISTINCT b) AS time2Nodes
方法3:子查询分别获取集合
通过子查询独立获取两个标签的节点集合:
RETURN (MATCH (a:time1) RETURN collect(a) AS time1Nodes).time1Nodes, (MATCH (b:time2) RETURN collect(b) AS time2Nodes).time2Nodes
内容的提问来源于stack exchange,提问作者Novabro

