Neo4j Cypher находит два непересекающихся узла

Я использую Neo4j, чтобы попытаться найти любой узел, не связанный с конкретным узлом «а». Вопрос, который у меня есть до сих пор:

MATCH p = shortestPath((a:Node {id:"123"})-[*]-(b:Node))
WHERE p IS NULL
RETURN b.id as b

Таким образом, он пытается найти кратчайший путь между a и b. Если путь не найден, возвращается идентификатор этого узла. Однако это приводит к тому, что мой запрос выполняется в течение нескольких минут, а затем вылетает, когда ему не хватает памяти. Мне было интересно, будет ли этот метод работать, и есть ли более эффективный способ? Любая помощь будет принята с благодарностью!

редактировать:

MATCH (a:Node {id:"123"})-[*]-(b:Node),
(c:Node)
WITH collect(b) as col, a, b, c
WHERE a <> b AND NOT c IN col
RETURN c.id 

Итак, col (collect (b)) содержит каждый узел, подключенный к a, поэтому, если c не находится в col, то c не подключен к a?


person ThatOneGuy    schedule 22.04.2017    source источник


Ответы (1)


Во-первых, вы даете этому MATCH невыполнимый предикат, поэтому он никогда не найдет кратчайшего пути.

Предложения WHERE связаны с предложениями MATCH, OPTIONAL MATCH и WITH, поэтому ваш запрос запрашивает кратчайший путь, где путь не существует. Это никогда ничего не вернет.

Кроме того, самый короткий путь будет начинаться с узла, к которому вы НЕ хотите подключаться, поэтому у него нет способа найти узлы, которые к нему не подключены.

Вероятно, самый простой способ приблизиться к этому - это ПОИСКПОЗ для всех узлов, подключенных к рассматриваемому узлу, а затем ПОИСКПОЗ для всех: узлы проверяют те, которые не входят в подключенный набор. Это означает, что вам не нужно будет выполнять кратчайший путь от каждого отдельного узла в базе данных, а просто проверять членство в коллекции.

Для этого вам понадобятся процедуры APOC, поскольку они имеют самые быстрые средства соответствия узлам в подграфе.

MATCH (a:Node {id:"123"})
CALL apoc.path.subgraphNodes(a, {}) YIELD node
WITH collect(node) as subgraph
MATCH (b:Node)
WHERE NOT b in subgraph
RETURN b.id as b

РЕДАКТИРОВАТЬ

Ваш отредактированный запрос, скорее всего, взорвется, что приведет к созданию огромного набора результатов (запрос построит набор результатов для каждого узла, доступного из вашего начального узла по уникальному пути в декартовом произведении с каждым узлом:).

Вместо этого идите шаг за шагом, собирайте отдельные узлы (потому что в противном случае вы получите несколько одинаковых узлов, которые могут быть достигнуты разными путями), и только после того, как у вас будет ваша коллекция, вы должны начать сопоставление узлов, которые не т в списке.

MATCH (:Node {id:"123"})-[*0..]-(b:Node)
WITH collect(DISTINCT b) as col
MATCH (a:Node)
WHERE NOT a IN col
RETURN a.id 
person InverseFalcon    schedule 22.04.2017
comment
Благодарить! Я не могу использовать процедуры APOC. Это выглядит подходящей альтернативой? (см. править) - person ThatOneGuy; 23.04.2017
comment
Я отредактировал свой ответ запросом, который должен исправить ваш альтернативный запрос. Имейте в виду, что сопоставление переменной длины Cypher не будет столь же эффективным, как процедура subgraphNodes () APOC, поскольку Cypher интересует уникальные пути, поэтому этот запрос все еще может истекать по тайм-ауту на больших графах. - person InverseFalcon; 23.04.2017