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

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

MATCH p = shortestPath((a:Node {id:"123"})-[*]-(b:Node))
WHERE p IS NULL
RETURN b.id as 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?

1 ответ

Решение

С одной стороны, вы даете этому MATCH невозможный предикат, который нужно выполнить, поэтому он никогда не найдет кратчайшего пути.

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

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

Вероятно, самый простой способ достичь этого - сопоставить все узлы, подключенные к рассматриваемому узлу, а затем сопоставить все: проверка узлов, не входящих в подключенный набор. Это означает, что вам не нужно будет делать shorttestPath для каждого отдельного узла в БД, просто проверка членства в коллекции.

Для этого вам понадобятся процедуры 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 
Другие вопросы по тегам