Отфильтруйте результат neo4j, верните отличную комбинацию идентификаторов узлов - PullRequest
0 голосов
/ 04 ноября 2019

У меня есть график с 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)

Я хочу вернуть набор узлов только один раз (независимо от того, сколько разных рейсов существует между ними), но линия with не работает. По сути, я хочу создать новый тип переменной «объект», который имеет три идентификатора в качестве своих свойств и отличается от них. Это возможно в neo4j? Если нет, есть ли обходной путь?

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Вы можете использовать функцию 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 может не потребоваться, так как не должно быть никакихрейсы (если «полет» совпадает с «полетом»), которые летят из аэропорта обратно в себя.

1 голос
/ 04 ноября 2019

Вы можете вернуть объект с ключами или массивом. Например:

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])
...