Найти количество узлов не в определенном шаблоне [Neo4j] - PullRequest
0 голосов
/ 13 сентября 2018

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

Базовый график выглядит следующим образом:

(User)-[]->(id)

, где узел пользователя может иметь несколько идентификаторов, а некоторые идентификаторы имеют несколько пользовательских узлов.Существует особый интерес

Match (u:User)-[]->(id)<-[]-(u2:User) 
where u <> u2 AND id(u) < id(u2) 
return u, id, u2

Я хочу найти всех пользователей НЕ в этом шаблоне.То есть найдите различное количество пользователей, которые не имеют связи с другим пользователем.Я на большой машине с 244 RAM, но все, что я пробовал, просто разрывает соединение через веб-интерфейс.График содержит 755 мм пользователей и 2B узлов + в целом.

Вот запрос, который прерывает

Match (u:User)
Where not ((u)-[]->()<-[]-(:User)
RETURN count(distinct User)

Я приму любое решение, включая APOC, если оно будет работать.enter image description here

1 Ответ

0 голосов
/ 14 сентября 2018

Основная проблема с вашим текущим запросом в том, что расширение убивает вас. Согласно объяснению, в среднем каждый пользователь подключен примерно к 2 идентификаторам. Поэтому Neo4j нужно в четыре раза увеличить объем памяти, который он использует для сохраненных строк (X2 #OfRows и X2 #OfColumnsPerRow в промежуточной таблице, прежде чем он сможет фильтровать при подключении к другому пользователю) (Отказ от ответственности: Cypher не гарантирует такое поведение, это просто возможно план, который может произойти)

Таким образом, вы хотите разработать свой запрос таким образом, чтобы свести к минимуму количество узлов, к которым Neo4j нужно прикоснуться, чтобы получить правильные результаты. В вашем случае ваш запрос эквивалентен запросу количества пользователей, у которых нет идентификатора, или они связаны с идентификатором, который является эксклюзивным для этого пользователя? (Поскольку эти 2 условия являются взаимоисключающими, нам не нужно беспокоиться о перекрытии)

Предполагается, что узлы идентификатора имеют метку: ID ...

MATCH (id:ID)
WHERE SIZE((:User)-->(id))=1
WITH COUNT(id) as count
MATCH (u:User)
WHERE NOT (u)-->(:ID)
RETURN count+COUNT(u) as count

Обратите внимание, что ребра и метки индексируются внутренне, поэтому для этого Neo4j не нужно ничего расширять. Нужно только сканировать по меткам, чтобы получить узлы, и сканировать таблицу ребер на предмет количества ребер (и при необходимости проверять метки на подключенных узлах. Такое поведение не гарантируется Cypher)


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

MATCH (id:ID)
WHERE SIZE((id)<--(:User)) > 1
MATCH (id)<--(u:User)
RETURN COUNT((:User))-COUNT(DISTINCT u) as count

Ваша другая проблема - это объем сдвига узлов, который необходимо подсчитать, и в зависимости от того, что все работает на сервере, и что выделено для Neo4j, это может быть немного больше Cypher ( apoc может что-то есть, но я ничего не нашел для подсчета шаблонов). Один из способов обойти это - отобразить результаты на странице (используя LIMIT и OFFSET), а затем программно запросить счетчик каждой страницы и суммировать их вместе (это имеет небольшую вероятность ошибки, основанную на частоте обновлений, но лучше, чем нет ничего)

...