Collections Cypher(Neo4j)中集合的并集和交集操作

Collections Cypher(Neo4j)中集合的并集和交集操作,collections,neo4j,union,cypher,intersection,Collections,Neo4j,Union,Cypher,Intersection,我需要计算Cypher中一组数组/集合的并集和交集。比如说,我将许多个人感兴趣的主题保存为每个节点的数组属性,我需要知道(1)给定组的每个成员感兴趣的主题;但我也需要知道(2)可能引起小组成员注意的话题 因此,将以下个人作为两人小组的成员: CREATE ({name: 'bill', interests: ["biking", "hiking", "fishing", "swimming"]}) CREATE ({name: 'joe', interests: ["swimming", "hi

我需要计算Cypher中一组数组/集合的并集和交集。比如说,我将许多个人感兴趣的主题保存为每个节点的数组属性,我需要知道(1)给定组的每个成员感兴趣的主题;但我也需要知道(2)可能引起小组成员注意的话题

因此,将以下个人作为两人小组的成员:

CREATE ({name: 'bill', interests: ["biking", "hiking", "fishing", "swimming"]})
CREATE ({name: 'joe', interests: ["swimming", "hiking", "biking", "tennis"]})
受此启发,我编写了以下脚本以满足我的需要:

交叉点(n∩ m、 兴趣)

回应:骑自行车、徒步旅行、游泳

工会∪ m、 兴趣)

回应:骑自行车、徒步旅行、游泳、钓鱼、网球

对于两人一组,这两种方法都非常有效。问题是联合脚本不可概括,需要为每个额外的组成员进一步扩展。这是因为没有做一个简单的
n∪ m、 兴趣,兴趣我要做的就是产生兴趣∩ m、 利益)∪ (n.利益-m.利益)∪ (m.interests-n.interests)
等于
n.interests∪ m、 兴趣
,但需要对组中的所有个人进行成对比较

因此,我的问题是:在Cypher中有没有更好的方法来生成两个集合/数组的并集,而不会在响应集合中产生冗余结果

另外,您可能已经注意到,这些兴趣并没有真正的顺序,所以我实际上将Neo4j系列视为集合


p.S.2我可能误解并错误地混淆了Cypher中收集和数组的概念,在这种情况下,请毫不犹豫地指出错误所在。

我认为您可以使用
reduce
来概括它,以生成您的收集

并且可能使用一个quantor谓词(ANY、ALL、SINGLE、NONE)

对于交叉口,类似这样的情况:

WITH [1,2,3] as a, [3,4,5] as b, [2,3,4] as c
REDUCE (res=[], x in a | case when x in b AND x in c then res + [x] else res)

WITH [1,2,3] as a, [3,4,5] as b, [2,3,4] as c
REDUCE (res=[], x in a | case when ALL(coll in [b,c] WHERE x in coll) then res + [x] else res)

但所有这些操作都不会有很好的运行时特性。

我最近解决了同样的问题,首先使用重复的并集,然后使用
distinct

MATCH (n {name:'bill'}), (m {name:'joe'})
UNWIND n.interests + m.interests AS interests
RETURN COLLECT(distinct interests) AS interests_union
具有并集和交集功能,这正是您需要的

MATCH (n {name:'bill'}), (m {name:'joe'})
RETURN apoc.coll.union(n.interests, m.interests) as interests_union,
       apoc.coll.intersection(n.interests, m.interests) as interests_intersection
以上内容可用于Neo4j 3.1及以上版本(支持用户定义的功能)。在Neo4j 3.0中,这些是过程,您需要将它们称为过程


这也很容易应用于多个集合,而不仅仅是两个集合。如果收集了集合,您可以在列表列表上运行REDUCE(),为所有集合应用并集或交集。

与您的问题无关:为什么不将兴趣建模为节点并与它们建立显式关系,而不是将结构隐藏在数组属性中?这只是一个简化的示例,但要回答您的问题:因为在我的应用程序中,这些属性大多是死数据,这意味着我很少访问它们。因此,我试图避免数据库模式出现不必要的增长和复杂性。这些节点每个都有一个属性,有时每个节点上有数百个属性,它们的作用很小。正如我所说的,交集很容易推广。问题在于Union,因为目前没有办法在Cypher中将已经存在的集合视为集合。与集合相反,集合将自动丢弃重复项。在这种情况下,a+b+c将返回a∪ B∪ c当作为一个集合处理时。
MATCH (n {name:'bill'}), (m {name:'joe'})
UNWIND n.interests + m.interests AS interests
RETURN COLLECT(distinct interests) AS interests_union
MATCH (n {name:'bill'}), (m {name:'joe'})
RETURN apoc.coll.union(n.interests, m.interests) as interests_union,
       apoc.coll.intersection(n.interests, m.interests) as interests_intersection