2017-02-11 9 views
0

Я начинаю с Neo4j и задаюсь вопросом об обнаружении узлов, подключенных к другому узлу длиной не более k краев (друг друга друга ... до k раз). Я проиллюстрирую пример из учебника самого Neo4j (я поставил команды создания графика внизу).Cypher предотвращает перечисление всех путей

match (e {name:"Emil"})-[*1..2]-(p) 
return DISTINCT e, p; 

Этот запрос будет возвращать узлы, подключенные к Эмилю, и узлы, подключенные к этим узлам. Моя проблема в том, что, похоже, это перечисляет КАЖДЫЙ путь длиной 1-2 от Эмиля, хотя мне все равно, перечисляя все пути. Из запроса ясно, что я только забочусь о узлах, подключенных к Эмилю на этом расстоянии, и перечисление всех возможных путей - это плохой способ реализовать этот запрос. Это проблема в больших плотных графах, поскольку сложность становится подавляющей.

Удалить DISTINCT и будет 8 записей, число уникальных путей длины 1-2 от Эмиля. Основываясь на моем тестировании на больших графиках, кажется, что DISTINCT является этапом последующей обработки, который не влияет на время выполнения запроса, хотя он устранит избыточный результат. Это верно?

Мой главный вопрос: есть ли способ сформировать запрос Cypher для этой проблемы, чтобы я не пересекал все уникальные пути, и сложность может быть уменьшена? Пожалуйста, дайте мне знать, если у меня есть недоразумение.

---- Команда для создания графика -----

CREATE (ee:Person { name: "Emil", from: "Sweden", klout: 99 }) 
CREATE (js:Person { name: "Johan", from: "Sweden", learn: "surfing" }), 
(ir:Person { name: "Ian", from: "England", title: "author" }), 
(rvb:Person { name: "Rik", from: "Belgium", pet: "Orval" }), 
(ally:Person { name: "Allison", from: "California", hobby: "surfing" }), 
(ee)-[:KNOWS {since: 2001}]->(js),(ee)-[:KNOWS {rating: 5}]->(ir), 
(js)-[:KNOWS]->(ir),(js)-[:KNOWS]->(rvb), 
(ir)-[:KNOWS]->(js),(ir)-[:KNOWS]->(ally), 
(rvb)-[:KNOWS]->(ally) 

ответ

0

Max De Марх в Neo написал большой blog post о таких запросах, поэтому переменная длиной матчей, где только интерес для отдельных узлов, а не путей, будет обнаружен и оптимизирован планировщиком запросов в будущей версии, вероятно, 3.2.

Тем временем, процедуры APOC имеют решение в своем вызове apoc.path.expandConfig(), когда вы указываете 'NODE_GLOBAL' как параметр уникальности.

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

match (e {name:"Emil"}) 
call apoc.path.expandConfig(e, {maxLevel:2, uniqueness:'NODE_GLOBAL'}) yield path 
WITH e, last(nodes(path)) as subgraph 
where e <> subgraph 
return e, subgraph; 
+0

Спасибо! Оба именно то, что я ищу. – steve