Обеспечить порядок отношений в многопутевых запросах - PullRequest
1 голос
/ 23 апреля 2019

Я рассматриваю neo4j как базу данных Graph, и запросы пути переменной длины будут очень важным вариантом использования. Теперь я думаю Я нашел пример запроса, который Cypher не будет поддерживать.

Основная проблема заключается в том, что я хочу рассматривать составные отношения как одно отношение. Позвольте привести пример: найти соучастников. Я сделал это, используя стандартную базу данных фильмов. Цель состоит в том, чтобы найти всех актеров, которые действовали вместе с Томом Хэнксом. Это можно найти с помощью запроса:

MATCH (tom {name: "Tom Hanks"})-[:ACTED_IN]->()<-[:ACTED_IN]-(a:Person) return a

Теперь, что, если мы хотим рекурсивно найти со-актеров со-актеров? Мы можем переписать указанный выше запрос:

MATCH (tom {name: "Tom Hanks"})-[:ACTED_IN*2]-(a:Person) return a

И тогда становится ясно, что мы можем сделать это с

MATCH (tom {name: "Tom Hanks"})-[:ACTED_IN*]-(a:Person) return a

Примечательно, что все пути нечетной длины исключаются, поскольку они не заканчиваются на Person.

Теперь я нашел запрос, который не могу понять, как сделать рекурсивный:

MATCH (tom {name: "Tom Hanks"})-[:ACTED_IN]->()<-[:DIRECTED]-()-[:DIRECTED]->()<-[:ACTED_IN]-(a:Person) return DISTINCT a

На словах все актеры, имеющие общего режиссера с Томом Хэнксом.

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

MATCH (tom {name: "Tom Hanks"})-[:ACTED_IN|DIRECTED*]-(a:Person) return DISTINCT a

Тем не менее, (кроме того, что не кажется, чтобы завершить вообще). Это также захватит соучастников. То есть он будет соответствовать путям вида

()-[:ACTED_IN]->()<-[:ACTED_IN]-()

Так что мне интересно: Можем ли мы как-то ограничить порядок, в котором возникают отношения в многопутевом запросе? Что-то вроде:

MATCH (tom {name: "Tom Hanks"}){-[:ACTED_IN]->()<-[:DIRECTED]-()-[:DIRECTED]->()<-[:ACTED_IN]-}*(a:Person) return DISTINCT a

Где * относится ко всему в фигурных скобках.

Ответы [ 2 ]

0 голосов
/ 24 апреля 2019

Здесь может помочь расширитель пути из Процедуры APOC , так как мы добавили возможность выражать повторяющиеся последовательности меток, отношений или обоих.

Вв этом случае, так как вы хотите сопоставить актера шаблона, а не режиссера (или любой из фильмов в пути), нам нужно указать, какие узлы в пути вы хотите вернуть, что требует либо использования labelFilter в дополнение к relationshipFilter или просто для использования комбинированного свойства конфигурации sequence, чтобы указать ожидаемые чередующиеся метки / отношения, и убедитесь, что мы используем фильтр конечных узлов на узле: Person в точке шаблона,вы хотите.

Вот как бы вы сделали это после установки APOC:

MATCH (tom:Person {name: "Tom Hanks"})
CALL apoc.path.expandConfig(tom, {sequence:'>Person, ACTED_IN>, *, <DIRECTED, *, DIRECTED>, *, <ACTED_IN', maxLevel:12}) YIELD path
WITH last(nodes(path)) as person, min(length(path)) as distance
RETURN person.name

Обычно мы будем использовать subgraphNodes() для них, поскольку это эффективно при расширении и сокращении путей к узлам, которые мыМы уже видели, но в этом случае мы хотим сохранить возможность повторного посещения уже посещенных узлов, так как они могут возникнуть в последующих итерацияхпоэтому, чтобы получить правильный ответ, мы не можем использовать этот или любой из проков, использующих уникальность NODE_GLOBAL.

Из-за этого нам нужно остерегаться исследовать слишком много путей, как перестановки отношений кисследование того, что путь подходит, будет стремительно расти, даже после того, как мы уже нашли все возможные отдельные узлы.Чтобы избежать этого, нам нужно добавить maxLevel, поэтому в этом случае я использую 12.

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

Свойство config sequence позволяет нам указать чередующиеся фильтрации меток и типов отношений для каждого шага в последовательности, начиная с начального узла.Мы используем символ фильтра конечного узла, > перед первой меткой Person (>Person), указывающий, что нам нужны только пути к узлу Person в этой точке последовательности (в качестве первого элемента в последовательности он также будетпоследний элемент в последовательности, как он повторяется).Мы используем подстановочный знак * для фильтра меток всех других узлов, что означает, что узлы находятся в белом списке и будут проходить независимо от их метки, но мы не хотим возвращать пути к этим узлам.

0 голосов
/ 24 апреля 2019

Если вы хотите увидеть всех актеров, которые снимались в фильмах, снятых режиссерами, которые снимали Тома Хэнкса, но которые никогда не снимались с Томом, вот один из способов:

MATCH (tom {name: "Tom Hanks"})-[:ACTED_IN]->(m)
MATCH (m)<-[:ACTED_IN]-(ignoredActor)
WITH COLLECT(DISTINCT m) AS ignoredMovies, COLLECT(DISTINCT ignoredActor) AS ignoredActors
UNWIND ignoredMovies AS movie
MATCH (movie)<-[:DIRECTED]-()-[:DIRECTED]->(m2)
WHERE NOT m2 IN ignoredMovies
MATCH (m2)<-[:ACTED_IN]-(a:Person)
WHERE NOT a IN ignoredActors
RETURN DISTINCT a

Верхние 2 MATCH предложения намеренно не объединены в одно предложение, поэтому узел Тома Хэнкса будет зафиксирован как ignoredActor. (Предложение MATCH отфильтровывает любой результат, который использует одно и то же отношение дважды.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...