Как запросить точный путь в neo4j и избежать декартового произведения? - PullRequest
0 голосов
/ 02 мая 2019

У меня около 3000 узлов с 7000 взаимосвязями на графике, но для презентации я хотел бы построить подграф, в котором я точно знаю, какие узлы мне нужны.

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

MATCH p1=(:DestinationNode)-[:IS_AT]->
(:CentiDegreeNode{x: 4714, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4715, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4716, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4717, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4718, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4718, y: 844})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 844}),
p2=(:DestinationNode)-[:IS_AT]->
(:CentiDegreeNode{x: 4718, y: 839})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4718, y: 840})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 840})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 841})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 842})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 844}),
p3=(:CentiDegreeNode{x: 4719, y: 844})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 845})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 846})
RETURN p1, p2, p3

Что я делаю не так? Как мне перефразировать запрос, чтобы он был выполнен в течение нескольких секунд? Обратите внимание, что x и y из CentiDegreeNode проиндексированы.

Первоначально я начал с направленных отношений (-[:CONNECTED_TO]->), но это было не так быстро.

Большое спасибо!

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Вы можете перефразировать ваш запрос, чтобы избежать декартово произведение , используя UNION

match path=(:A)-[:K]->(:B) 
return path
union
match path=(:D)-[:H]->(:C) 
return path
union
match path=(:F)-[:L]->(:G}) 
return path

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

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

match path=(:A)-[:K]->(:B) 
with collect( path)  as path_list_1
match path=(:D)-[:H]->(:C) 
with path_list_1, collect( path)  as path_list_2
match path=(:F)-[:L]->(:G})
with path_list_1, path_list_2 , collect( path)  as path_list_3
return path_list_1, path_list_2 , path_list_3

Теперь с этим мы можем добиться оптимального сбора и классификации путей.

Если вы используете более старую версию, где WITH недоступна, вы можете сделать что-то подобное и затем агрегировать на основе path_types в вашем приложении.

match path=(:A)-[:K]->(:B) 
return path, 1 as path_type
union
match path=(:D)-[:H]->(:C) 
return path, 2 as path_type
union
match path=(:F)-[:L]->(:G}) 
return path, 3 as path_type 

Cheers !!

1 голос
/ 02 мая 2019

Когда вы говорите, что "x и y из CentiDegreeNode проиндексированы", мы надеемся, что вы имели в виду, что оба свойства используются вместе в одном индексе: :CentiDegreeNode(x, y). Это было бы более производительным.

Разделение 3 путей на WITH может помочь (это может зависеть от версии neo4j). Также, собирая пути по пути, вы можете избежать декартовых произведений.

MATCH p1=(:DestinationNode)-[:IS_AT]->
(:CentiDegreeNode{x: 4714, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4715, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4716, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4717, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4718, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4718, y: 844})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 844})
WITH COLLECT(p1) AS p1s
MATCH p2=(:DestinationNode)-[:IS_AT]->
(:CentiDegreeNode{x: 4718, y: 839})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4718, y: 840})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 840})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 841})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 842})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 843})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 844})
WITH p1s, COLLECT(p2) AS p2s
MATCH p3=(:CentiDegreeNode{x: 4719, y: 844})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 845})-[:CONNECTED_TO*1]-
(:CentiDegreeNode{x: 4719, y: 846})
RETURN p1s, p2s, COLLECT(p3) AS p3s
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...