Как фильтровать по шаблону в запросе Cypher переменной длины - PullRequest
0 голосов
/ 22 октября 2018

У меня очень простой граф с 5 узлами (названными n1 - n5), 1 типом узла (: Node) и 2 типами отношений (: r1,: r2).Узлы и отношения расположены следующим образом (извинения за искусство ascii):

(n1)-[:r1]->(n2)-[:r1]->(n3)
(n1)-[:r2]->(n4)-[:r2]->(n3)
(n1)-[:r1]->(n5)-[:r2]->(n3)

У меня есть запрос с использованием пути переменной длины.Я ожидал, что смогу ограничить возвращаемые пути, описав конкретный шаблон в предложении WHERE:

MATCH p = (n:Node {name: 'n1'})-[*..2]->()
WHERE (n)-[:r1]->()-[:r1]->()
RETURN p

Проблема в том, что ответ возвращает все возможные пути.Мой вопрос;Можно ли отфильтровать возвращаемые пути при указании пути переменной длины в запросе?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Ваш запрос возвращает все пути, потому что ваше предложение WHERE (оператор фильтра) применяется перед оператором VarLengthExpand:

+-----------------------+----------------+------+---------+-----------------+-------------------+----------------------+----------------------------+------------------------------------------------------------------------------------------------------------+
| Operator              | Estimated Rows | Rows | DB Hits | Page Cache Hits | Page Cache Misses | Page Cache Hit Ratio | Variables                  | Other                                                                                                      |
+-----------------------+----------------+------+---------+-----------------+-------------------+----------------------+----------------------------+------------------------------------------------------------------------------------------------------------+
| +ProduceResults       |              0 |    4 |       0 |               0 |                 0 |               0.0000 | anon[32], anon[41], n, p   |                                                                                                            |
| |                     +----------------+------+---------+-----------------+-------------------+----------------------+----------------------------+------------------------------------------------------------------------------------------------------------+
| +Projection           |              0 |    4 |       0 |               0 |                 0 |               0.0000 | p -- anon[32], anon[41], n | {p : PathExpression(NodePathStep(Variable(n),MultiRelationshipPathStep(Variable(),OUTGOING,NilPathStep)))} |
| |                     +----------------+------+---------+-----------------+-------------------+----------------------+----------------------------+------------------------------------------------------------------------------------------------------------+
| +VarLengthExpand(All) |              0 |    4 |       7 |               0 |                 0 |               0.0000 | anon[32], anon[41] -- n    | (n)-[:*..2]->()                                                                                            |
| |                     +----------------+------+---------+-----------------+-------------------+----------------------+----------------------------+------------------------------------------------------------------------------------------------------------+
| +Filter               |              0 |    1 |       6 |               0 |                 0 |               0.0000 | n                          | n.name = {  AUTOSTRING0}; GetDegree(Variable(n),Some(RelTypeName(KNOWS)),OUTGOING) > 0                     |
| |                     +----------------+------+---------+-----------------+-------------------+----------------------+----------------------------+------------------------------------------------------------------------------------------------------------+
| +NodeByLabelScan      |              4 |    4 |       5 |               0 |                 0 |               0.0000 | n                          | :Crew                                                                                                      |
+-----------------------+----------------+------+---------+-----------------+-------------------+----------------------+----------------------------+------------------------------------------------------------------------------------------------------------+

Это должно помочь вам:

MATCH p = (n:Node {name: 'n1'})-[*..2]->()
WITH n, relationships(p)[0] as rel0, relationships(p)[1] as rel1, p
MATCH (n)-[rel0:r1]->()-[rel1:r1]->()
RETURN p
0 голосов
/ 22 октября 2018

Если все отношения или узлы должны придерживаться одного и того же предиката, это легко.Вам понадобится переменная для пути, и вам нужно будет использовать all() (или none()) в предложении WHERE, чтобы применить предикат для всех отношений или узлов в вашем пути:

MATCH p = (n:Node {name: 'n1'})-[*..2]->()
WHERE all(rel in relationships(p) WHERE type(rel) = 'r1')
RETURN p

Тем не менее, когда все, что вам нужно, - это чтобы все отношения в пути var-length были одного типа (или типов, если вы хотите несколько), лучше всего это сделать в самом шаблоне:

MATCH p = (n:Node {name: 'n1'})-[:r1*..2]->()
RETURN p

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

РЕДАКТИРОВАТЬ

Вы упомянули в комментариях, что ваш случай имеет дело с последовательностями отношений различной длины.Хотя расширители пути APOC могут помочь, есть несколько ограничений:

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

  2. Существуют ограничения дляподдержка последовательности отношений для расширителей пути.Мы можем определять последовательности любой длины и принимать несколько типов отношений на каждом шаге в последовательности, но в настоящее время мы не поддерживаем расходящиеся последовательности ((r1, затем r2, затем r3) или (r2, затем r5, затем r6)).

Если мы хотим сделать трехшаговую последовательность r1 (входящий), r2 (исходящий), затем r3 или r4 (с r3 в любом направлении и r4 исходящим), повторяя последовательность вверх3 раза мы могли бы сделать это следующим образом:

MATCH (n:Node {name: 'n1'})
CALL apoc.path.expandConfig(n, {relationshipFilter:'<r1, r2>, r3 | r4>', minLevel:1, maxLevel:9) YIELD path
RETURN path

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

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

...