我目前正在开始使用Neo4J及其查询语言cypher。 我有多个查询遵循相同的模式。
我正在对SQL数据库和Neo4J进行一些比较。
在我的Neo4J数据库中,我有一种标签(人)和一种关系(FRIENDSHIP)。该人具有propetyies personID,姓名,电子邮件,电话。 现在我想拥有第n个学位的朋友。我也想过滤掉那些也是学历较低的朋友。 举个例子,如果我想搜索3度的朋友,我想过滤掉那些也是朋友第一和/或第二学位的朋友。
这是我的查询类型:
MATCH (me:person {personID:'1'})-[:FRIENDSHIP*3]-(friends:person)
WHERE NOT (me:person)-[:FRIENDSHIP]-(friends:person)
AND NOT (me:person)-[:FRIENDSHIP*2]-(friends:person)
RETURN COUNT(DISTINCT friends);
我在某处找到了类似的东西。
此查询有效。
我的问题是,如果我寻求更高程度的友谊和/或如果人数变得更多,这种查询模式会慢得多。
所以我真的很感激,如果有人可以帮我优化这个。
答案 0 :(得分:1)
如果你只想处理3的深度,这应该返回距离3度但不小于3度的不同节点:
MATCH (me:person {personID:'1'})-[:FRIENDSHIP]-(f1:person)-[:FRIENDSHIP]-(f2:person)-[:FRIENDSHIP]-(f3:person)
RETURN apoc.coll.subtract(COLLECT(f3), COLLECT(f1) + COLLECT(f2) + me) AS result;
上述查询使用APOC函数apoc.coll.subtract从结果中删除不需要的节点。该函数还确保集合包含不同的元素。
以下查询更通用,并且应该适用于任何给定深度(仅通过替换*
之后的数字)。例如,此查询的深度为4:
MATCH p=(me:person {personID:'1'})-[:FRIENDSHIP*4]-(:person)
WITH NODES(p)[0..-1] AS priors, LAST(NODES(p)) AS candidate
UNWIND priors AS prior
RETURN apoc.coll.subtract(COLLECT(DISTINCT candidate), COLLECT(DISTINCT prior)) AS result;
答案 1 :(得分:0)
Cypher的可变长度关系匹配问题在于它正在寻找到该深度的所有可能路径。当你感兴趣的是某些深度的节点而不是它们的路径时,这会导致不必要的性能问题。
APOC's path expander使用' NODE_GLOBAL' uniqueness
是一种更有效的方法,可以在包含深度的节点上进行匹配。
使用' NODE_GLOBAL'唯一性,节点在遍历期间只访问过一次。因此,当我们将路径扩展器的minLevel
和maxLevel
设置为相同时,结果是该级别的节点不存在于任何较低级别,这正是结果你想要得到。
安装APOC后尝试此查询:
MATCH (me:person {personID:'1'})
CALL apoc.path.expandConfig(me, {uniqueness:'NODE_GLOBAL', minLevel:4, maxLevel:4}) YIELD path
// a single path for each node at depth 4 but not at any lower depth
RETURN COUNT(path)
当然,当你有机会时,你想要参数化你的输入(personID,level)。