过滤 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" 相同)从机场飞回自己。