过滤 neo4j 结果,return 个不同的节点 ID 组合
Filter neo4j result, return distinct combination of node IDs
我有一个包含 Airport
个节点和 Flight
关系的图表,我想从一个特定节点找到三角形,其中边的长度都在彼此的 10% 以内。
MATCH path = (first:Airport{ID: 12953})-[f1:Flight]->
(second:Airport)-[f2:Flight]->
(third:Airport)-[f3:Flight]->
(last:Airport{ID: 12953})
WHERE second.ID <>first.ID AND
third.ID <>first.ID AND
f1.Distance<=(1.1*f2.Distance) AND
f1.Distance<=(1.1*f3.Distance) AND
f2.Distance<=(1.1*f1.Distance) AND
f2.Distance<=(1.1*f3.Distance) AND
f3.Distance<=(1.1*f1.Distance) AND
f3.Distance<=(1.1*f2.Distance)
WITH (first.ID, second.ID, third.ID) as triplet
return count(DISTINCT triplet)
我只想 return 一组节点一次(无论它们之间存在多少不同的航班),但是 with
行不起作用。基本上,我想要创建的是一种新型变量 "object",它具有三个 ID 作为其属性,并且 运行 是不同的。这在 neo4j 中可能吗?如果没有,是否有一些解决方法?
您可以 return 带有键或数组的对象。例如:
UNWIND range(1, 10000) AS i
WITH
{
id1: toInteger(rand()*3),
id2: toInteger(rand()*3),
id3: toInteger(rand()*3)
} AS triplet
RETURN DISTINCT triplet
或
UNWIND range(1, 10000) AS i
WITH
[ toInteger(rand()*3), toInteger(rand()*3), toInteger(rand()*3) ] AS triplet
RETURN DISTINCT triplet
更新。您可以通过在查询中重复使用变量、指定路径长度和使用列表函数来简化查询:
MATCH ps = (A:Airport {ID: 12953})-[:Flight*3]->(A)
WITH ps
WHERE reduce(
total = 0,
rel1 IN relationships(ps) |
total + reduce(
acc = 0,
rel2 IN relationships(ps) |
acc + CASE WHEN rel1.Distance <= 1.1 * rel2.Distance THEN 0 ELSE 1 END
)) = 0
RETURN count(DISTINCT [n IN nodes(ps) | n.ID][0..3])
您可以使用 APOC 函数 apoc.coll.sort 对每个包含 3 个 ID
的列表进行排序,这样 DISTINCT
选项将正确处理具有相同 ID
的列表一样的。
这是一个使用 APOC 函数的简化查询:
MATCH path = (first:Airport{ID: 12953})-[f1:Flight]->
(second:Airport)-[f2:Flight]->
(third:Airport)-[f3:Flight]->
(first)
WHERE second <> first <> third AND
f2.Distance<=(1.1*f1.Distance)>=f3.Distance AND
f1.Distance<=(1.1*f2.Distance)>=f3.Distance AND
f1.Distance<=(1.1*f3.Distance)>=f2.Distance
RETURN COUNT(DISTINCT apoc.coll.sort([first.ID, second.ID, third.ID]]))
注意:second <> first
测试可能没有必要,因为不应该有任何航班(如果 "flight" 与 "leg" 相同)从机场飞回自己。
我有一个包含 Airport
个节点和 Flight
关系的图表,我想从一个特定节点找到三角形,其中边的长度都在彼此的 10% 以内。
MATCH path = (first:Airport{ID: 12953})-[f1:Flight]->
(second:Airport)-[f2:Flight]->
(third:Airport)-[f3:Flight]->
(last:Airport{ID: 12953})
WHERE second.ID <>first.ID AND
third.ID <>first.ID AND
f1.Distance<=(1.1*f2.Distance) AND
f1.Distance<=(1.1*f3.Distance) AND
f2.Distance<=(1.1*f1.Distance) AND
f2.Distance<=(1.1*f3.Distance) AND
f3.Distance<=(1.1*f1.Distance) AND
f3.Distance<=(1.1*f2.Distance)
WITH (first.ID, second.ID, third.ID) as triplet
return count(DISTINCT triplet)
我只想 return 一组节点一次(无论它们之间存在多少不同的航班),但是 with
行不起作用。基本上,我想要创建的是一种新型变量 "object",它具有三个 ID 作为其属性,并且 运行 是不同的。这在 neo4j 中可能吗?如果没有,是否有一些解决方法?
您可以 return 带有键或数组的对象。例如:
UNWIND range(1, 10000) AS i
WITH
{
id1: toInteger(rand()*3),
id2: toInteger(rand()*3),
id3: toInteger(rand()*3)
} AS triplet
RETURN DISTINCT triplet
或
UNWIND range(1, 10000) AS i
WITH
[ toInteger(rand()*3), toInteger(rand()*3), toInteger(rand()*3) ] AS triplet
RETURN DISTINCT triplet
更新。您可以通过在查询中重复使用变量、指定路径长度和使用列表函数来简化查询:
MATCH ps = (A:Airport {ID: 12953})-[:Flight*3]->(A)
WITH ps
WHERE reduce(
total = 0,
rel1 IN relationships(ps) |
total + reduce(
acc = 0,
rel2 IN relationships(ps) |
acc + CASE WHEN rel1.Distance <= 1.1 * rel2.Distance THEN 0 ELSE 1 END
)) = 0
RETURN count(DISTINCT [n IN nodes(ps) | n.ID][0..3])
您可以使用 APOC 函数 apoc.coll.sort 对每个包含 3 个 ID
的列表进行排序,这样 DISTINCT
选项将正确处理具有相同 ID
的列表一样的。
这是一个使用 APOC 函数的简化查询:
MATCH path = (first:Airport{ID: 12953})-[f1:Flight]->
(second:Airport)-[f2:Flight]->
(third:Airport)-[f3:Flight]->
(first)
WHERE second <> first <> third AND
f2.Distance<=(1.1*f1.Distance)>=f3.Distance AND
f1.Distance<=(1.1*f2.Distance)>=f3.Distance AND
f1.Distance<=(1.1*f3.Distance)>=f2.Distance
RETURN COUNT(DISTINCT apoc.coll.sort([first.ID, second.ID, third.ID]]))
注意:second <> first
测试可能没有必要,因为不应该有任何航班(如果 "flight" 与 "leg" 相同)从机场飞回自己。