Cypher(Neo4j)馆藏的联合和交叉运营

时间:2014-05-01 15:00:19

标签: collections neo4j union cypher intersection

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

因此,请将以下人员作为一组两人的成员:

CREATE ({name: 'bill', interests: ["biking", "hiking", "fishing", "swimming"]})
CREATE ({name: 'joe', interests: ["swimming", "hiking", "biking", "tennis"]})

this great answer的启发我编写了以下脚本来获得我需要的东西:

交叉点(n.interests∩m.interests)

MATCH (n {name:'bill'}), (m {name:'joe'})
RETURN FILTER(x IN n.interests WHERE x IN m.interests)

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

联盟(n.interests∪m.interests)

MATCH (n {name:'bill'}), (m {name:'joe'})
RETURN FILTER(x IN n.interests WHERE x IN m.interests)+
FILTER(x IN n.interests WHERE NOT(x IN m.interests))+
FILTER(x IN m.interests WHERE NOT(x IN n.interests))

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

对于两人一组,两者都很好。问题是union脚本不可推广,需要针对每个其他组成员进一步扩展。这是因为我不是做一个直截了当的n.interests ∪ m.interests,而是通过产生等于(n.interests ∩ m.interests) ∪ (n.interests - m.interests) ∪ (m.interests - n.interests)的{​​{1}}而走得很远,但需要对组中所有个体进行成对比较。

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

P.S。你可能已经注意到这些兴趣并没有真正有序,所以我实际上把Neo4j集合视为集合。

P.S.2我可能会误解并错误地将Cypher中的收集和数组概念混为一谈,在这种情况下,请不要犹豫,指出错误是什么。

3 个答案:

答案 0 :(得分:2)

APOC Procedures具有联合和交集函数,应该正是您所需要的。

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()以应用所有集合的并集或交集。

答案 1 :(得分:1)

我最近通过首先使用重复的联合解决了同样的问题,然后使用distinct

进行重复数据删除
MATCH (n {name:'bill'}), (m {name:'joe'})
UNWIND n.interests + m.interests AS interests
RETURN COLLECT(distinct interests) AS interests_union

答案 2 :(得分:0)

我认为你可以使用reduce来概括它来制作你的收藏品。

并且可能使用其中一个quantor-predicates(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)

但是所有这些操作都没有真正好的运行时特性。