Neo4j алгоритм возврата графиков
У меня сложный вопрос о Neo4j и о том, что может сделать Traversal.
Представьте, что у вас есть следующий график Neo4j
Моя идея состоит в том, чтобы пройти весь граф, и если я найду "ложный" узел, разверну этот статус для его соседей и так далее, и, наконец, в этом примере мы получим все узлы со статусом "ложный". (В реальной жизни у меня есть больше условий, чтобы установить этот статус в true или false при обходе, но я немного упростил его для вопроса)
Я думаю, что мне нужен какой-то алгоритм возврата, чтобы сделать это, но в Neo4j я не знаю, как это сделать, или если это вообще возможно. Кроме того, этот график может быть очень огромным графиком.
Как бы вы сделали это с Java и Neo4j?
Благодарю.
2 ответа
Для эффективного сопоставления с достижимыми узлами, есть два варианта, которые, как правило, работают хорошо.
В Neo4j 3.2.x есть эффективное средство для сопоставления со всеми различными достижимыми узлами посредством сопоставления отношений с переменными плюс использование DISTINCT, но для этого требуется верхняя граница отношения с переменной длиной. Использование достаточно большого числа должно работать. Что-то вроде:
MATCH (:SomeLabel{someProperty:false})-[*..999999]->(x)
WITH distinct x
SET x.someProperty = false
В противном случае процедуры APOC предлагают apoc.path.subgraphNodes(), который также обеспечивает эффективное сопоставление с достижимыми узлами в подграфе:
MATCH (start:SomeLabel{someProperty:false})
CALL apoc.path.subgraphNodes(start, {}) YIELD node
SET node.someProperty = false;
РЕДАКТИРОВАТЬ
Чтобы добавить больше деталей для первого варианта (почему бы просто не использовать *
и зачем использовать DISTINCT), имейте в виду, что по умолчанию Cypher будет соответствовать всем возможным путям, когда мы используем *
, даже если эти пути заканчиваются на том же узле, что и ранее сопоставленный путь. Это может стать неэффективным в достаточно связанном графе (когда у нас нет разумной верхней границы, и мы не используем LIMIT), с возможностью разорвать вашу кучу или зависать бесконечно.
Этого особенно следует избегать, когда нас не интересуют все возможные пути, только все возможные узлы, которые доступны.
В Neo4j 3.2 была введена оптимизация, называемая pruning-var expand, которая изменяет логику обхода в случае, когда все следующее верно:
- У нас есть расширение var-длины
- Мы никоим образом не ссылаемся на путь (например, устанавливая переменную пути для шаблона соответствия или устанавливая переменную в отношении var-length)
- У нас есть верхняя граница для разложения длины var
- Мы просим DISTINCT узлы или значения, полученные из расширения
В основном, когда запрос таков, что ясно, что мы хотим отличные узлы (или значения от разных узлов) от расширения var-length и не заботимся о путях.
Затем планировщик будет использовать сокращение var var (вы можете подтвердить, проверив план запроса из EXPLAIN или PROFILE), чтобы эффективно сопоставить достижимые узлы.
Я не знаю, полностью ли я понял ваш вопрос, но я считаю, что достаточно простого запроса Cypher. Что-то вроде:
MATCH ({someProperty : false})-[*]-(neighbours)
SET neighbours.someProperty = false