Добавление фильтра свойств в запрос cypher увеличивает объем памяти, почему?

#neo4j #cypher

#neo4j #cypher

Вопрос:

Я пытаюсь написать запрос, который исследует график DAG-типа (спецификацию) для всех путей построения, ведущих к определенному номеру детали (второе СОВПАДЕНИЕ), среди всех деталей, связанных с данным продуктом (первое СОВПАДЕНИЕ). Есть странное поведение, которого я не понимаю:

Этот запрос выполняется в разумные сроки с использованием Neo4j community edition (~ 2 с):

 WITH '12345' as snid, 'ABCDE' as pid
MATCH (m:Product {full_sn:snid})-[:uses]->(p:Part)
WITH snid, pid, collect(p) AS mparts
MATCH path=(anc:Part)-[:has*]->(child:Part)
WHERE ALL(node IN nodes(path) WHERE node IN mparts)
WITH snid, path, relationships(path)[-1] AS rel, 
nodes(path)[-2] AS parent, nodes(path)[-1] AS child
RETURN stuff I want
 

Однако, чтобы получить нужный мне запрос, я должен добавить фильтр для дочернего элемента, используя номер детали pid во втором операторе СОПОСТАВЛЕНИЯ:

 MATCH path=(anc:Part)-[:has*]->(child:Part {pn:pid})
 

И когда я пытаюсь запустить новый запрос, браузер neo4j сообщает, что недостаточно памяти. (Нео.TransientError.Общая информация.OutOfMemoryError). Когда я запускаю его с помощью EXPLAIN , количество обращений к базе данных увеличивается до 10 миллиардов, как будто я прошу у него массивный картезианский продукт: но все, что я сделал, это добавил ограничение для дочернего элемента, так что это должно сократить пространство поиска, не так ли?

Я также попытался добавить индекс к :Part(pn). Теперь профиль, показанный EXPLAIN, выглядит очень эффективным, но у меня все та же ошибка памяти.

Если кто-нибудь может помочь мне понять, почему это изменение между двумя запросами вызывает проблемы, я был бы очень признателен!

С наилучшими пожеланиями,

Ben

Ответ №1:

 MATCH path=(anc:Part)-[:has*]->(child:Part)
 

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

    OPTIONAL MATCH path=(anc:Part)-[:has*]->(child:Part)
 

Это концептуально (и грубо) похоже на внутреннее соединение в SQL.

Комментарии:

1. Привет, Дэвид, спасибо за ответ. * является преднамеренным. Моя проблема на самом деле состоит в том, чтобы понять, почему требования к памяти запроса увеличиваются, когда я добавляю ограничение на шаблон.