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