Как эффективно удалить узлы, которые не соединяют два разных узла целевого типа? - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть база данных Neo4j с такими отношениями: (:Person)-[:KNOWS]-(:Target)

Я хотел бы удалить всех людей, которые не связаны хотя бы с двумя разными целями благодаря запросу Cypher.

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

MATCH (n:Person)
OPTIONAL MATCH (n)-[*]-(t:Target)
WITH n, COUNT(t) AS nb_targets
WHERE NOT n:Target AND nb_targets < 2
RETURN n

Запрос даже не выполняется из-за его неэффективности ...

Примечание: у меня всего несколько целей и многочеловек

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

[ОБНОВЛЕНО]

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

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

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

MATCH (n:Person) WHERE NOT n:Target
OPTIONAL MATCH (n)-[:KNOWS*..6]-(t:Target)
WITH n, COUNT(DISTINCT t) AS nb_targets
WHERE nb_targets < 2
RETURN n

Чтобы исключить всех людей, которые не являются потенциальными подозреваемыми (включая тех, у кого более 6 прыжков из любогоцель), затем вы можете сначала идентифицировать всех подозреваемых и удалить людей, которые не являются ни целями, ни подозреваемыми:

MATCH (n:Person) WHERE NOT n:Target
OPTIONAL MATCH (n)-[:KNOWS*..6]-(t:Target)
WITH n, COUNT(DISTINCT t) AS nb_targets
WHERE nb_targets >= 2
WITH COLLECT(n) AS suspects
MATCH (m:Person)
WHERE NOT m:Target AND NOT m IN suspects
DETACH DELETE m
0 голосов
/ 08 февраля 2019

Cypher заинтересован в возвращении всех возможных путей, которые соответствуют шаблону, поэтому он не преуспеет с неограниченным запросом переменной длины, как этот.

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

Если вам нужен запрос только для возврата тех, которые не имелихотя бы 2 цели, тогда этот запрос должен работать:

MATCH (n:Person)
WHERE NOT n:TARGET
CALL apoc.path.subgraphNodes(n, {labelFilter:'>TARGET', limit:2, optional:true}) YIELD node
WITH n, count(node) AS nb_targets
WHERE nb_targets < 2
RETURN n
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...