следить за всеми связями, кроме определенных

#neo4j #cypher

#neo4j #шифр

Вопрос:

Как я могу сказать cypher, чтобы ОН НЕ следовал определенному отношению / краю?

Например, у меня есть a :NODE , который связан с другим :NODE через :BUDDY связь. Кроме того, каждый :NODE связан :STUFF с произвольной глубиной произвольными ребрами, которые НЕ имеют типа :BUDDY . Теперь я хочу добавить сокращенное отношение от каждого :NODE к своему :STUFF . Однако я не включаю :STUFF его :BUDDIES .

 (:NODE)-[:BUDDY]->(:NODE)

(:NODE)-[*]->(:STUFF)
 

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

 MATCH (n:Node)-[*]->(s:STUFF) WHERE NOT (n)-[:BUDDY]->()-[*]->(s) CREATE (n)-[:HAS]->(s)
 

Однако у меня есть некоторые проблемы с этим запросом:

1) Если я когда-нибудь добавлю :BUDDY связь не напрямую между :NODE дочерними элементами :NODE запроса, они будут использовать эту связь для сопоставления. Возможно, это не предназначено, поскольку я вообще не хочу включать приятелей.

2) Объяснение говорит мне, что neo4j выполняет сопоставление (:NODE)-[*]->(:STUFF) , а затем AntiSemiApply шаблон (n)-[:BUDDY]->() . В результате он сопоставляет весь график, чтобы затем отменить сопоставление большинства найденных соединений. Это кажется неэффективным, и запрос выполняется медленнее, чем мне хотелось бы (как бы субъективно это ни звучало).

Одно (плохое) исправление заключается в ограничении глубины (:NODE)-[*]->(:STUFF) via (:NODE)-[*..XX]->(:STUFF) . Однако я не могу гарантировать эту глубину, если не использую смехотворно большое число для наихудших сценариев.

На самом деле я просто хотел бы сказать neo4j, чтобы он просто не следовал определенным отношениям. Например MATCH (n:NODE)-[ALLBUT(:BUDDY)*]->(s:STUFF) CREATE (n)-[:HAS]->(s) , Как я могу добиться этого без необходимости перечислять все разрешенные соединения и соединять их с помощью a | (что действительно быстро, но мне приходится вручную отслеживать все возможные отношения)?

Ответ №1:

Один из вариантов для этой конкретной схемы — явно пройти мимо точки, где BUDDY связь вызывает беспокойство, а затем выполнить все неограниченные перемещения, которые вам нравятся оттуда. Затем вам нужно применить фильтр только к одноэтапным связям:

 MATCH (n:Node) -[r]-> (leaf)
WHERE NOT type(r) = 'BUDDY'
WITH n, leaf
MATCH (leaf) -[*] -> (s:Stuff)
WITH n, COLLECT(DISTINCT leaf) AS leaves, COLLECT(DISTINCT s) AS stuff
RETURN n, [leaf IN leaves WHERE leaf:Stuff]   stuff AS stuffs
 

Другой вариант — установить apoc и изучить процедуру расширения пути, которая позволяет вам вносить в черный список метки узлов (например,: Node) из вашего запроса path, что может работать так же хорошо, в зависимости от вашего графика. Смотрите здесь .

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

1. решение будет в порядке, если я не буду добавлять :BUDDY отношения глубже в график. Я посмотрю на apoc.

Ответ №2:

Мое окончательное решение — создать строку из набора

{relations}{relations_id_do_not_want}

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

Ответ №3:

Вы могли бы использовать условие типа nrelationship:

 MATCH (:Node)-[r:REL]->(:OtherNode)
WHERE NOT type(r) = 'your_unwanted_rel_type'
 

Хотя у меня нет никаких подсказок о perf