【问题标题】:How to filter by pattern in a variable length Cypher query如何在可变长度 Cypher 查询中按模式过滤
【发布时间】:2019-03-26 13:14:06
【问题描述】:

我有一个非常简单的图,它有 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

问题是响应返回所有可能的路径。我的问题;在查询中指定可变长度路径时是否可以过滤返回的路径?

【问题讨论】:

  • 响应不包含“所有可能的路径”。它包含您的查询所要求的内容:长度为 1 或 2 的所有路径,其中第一个节点满足 2 个条件 - 它的 name 值为 n1 并且它具有长度为 2 的传出路径,仅涉及 r1 关系。如果这不是您想要的,那么您必须将查询调整为更具体。

标签: filter neo4j path variable-length


【解决方案1】:

如果所有关系或节点都必须遵守同一个谓词,这很容易。您需要一个路径变量,并且需要在 WHERE 子句中使用 all()(或 none())来为路径中的所有关系或节点应用谓词:

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 path expanders 可能会有所帮助。

编辑

您在 cmets 中提到您的案例处理不同长度的关系序列。虽然 APOC 路径扩展器可能会有所帮助,但它有一些限制:

  1. 路径扩展器当前对节点标签和关系类型进行操作,但不是属性,因此如果您的扩展依赖于属性上的谓词,则路径扩展器将无法在扩展期间为您处理,这将必须通过过滤之后的路径扩展器结果来完成。

  2. 对路径扩展器的关系序列支持存在限制。我们可以定义任意长度的序列,并且可以在序列的每一步接受多种关系类型,但我们目前不支持发散序列((r1 then r2 then r3)或(r2 then r5 then r6))。

如果我们想要执行 r1(传入)、r2(传出)、然后 r3 或 r4(r3 在任一方向,r4 传出)的 3 步序列,重复该序列最多 3 次,我们可以这样做像这样:

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

请注意,我们可以在过滤器中为每个关系提供不同的方向,或者如果我们不关心方向,则完全不使用箭头。

标签过滤更复杂,但到目前为止,我在示例中没有看到任何需要。

【讨论】:

  • 感谢您的回复。我已经知道以您描述的方式应用谓词。我没有在我的问题中说清楚,但是,正如您在最后一点中提到的,我对更复杂的情况更感兴趣,在这些情况下,我可以过滤一组特定的关系序列,长度不等。我看过路径扩展器,但我不清楚如何应用这些,示例似乎非常稀缺。我再看看,谢谢。
【解决方案2】:

您的查询返回所有路径,因为您的 WHERE 子句(过滤器运算符)在 VarLengthExpand 运算符之前应用:

+------------------------+----------------+------+- --------+-----------------+--------+--- -------------------+----------------------------+- -------------------------------------------------- -------------------------------------------------- --------+ |运算符 |估计行数 |行 |数据库命中 |页面缓存命中 |页面缓存未命中 |页面缓存命中率 |变量 |其他 | +------------------------+----------------+------+- --------+-----------------+--------+--- -------------------+----------------------------+- -------------------------------------------------- -------------------------------------------------- --------+ | +生产结果 | 0 | 4 | 0 | 0 | 0 | 0.0000 |匿名[32],匿名[41],n,p | | | | +----------------+------+---------+------------- --+--------------------+----------+---- ---------------------+---------------------------- -------------------------------------------------- ---------------------------------+ | +投影 | 0 | 4 | 0 | 0 | 0 | 0.0000 | p -- anon[32],anon[41],n | {p : PathExpression(NodePathStep(Variable(n),MultiRelationshipPathStep(Variable(),OUTGOING,NilPathStep)))} | | | +----------------+------+---------+------------- --+--------------------+----------+---- ---------------------+---------------------------- -------------------------------------------------- ---------------------------------+ | +VarLengthExpand(全部) | 0 | 4 | 7 | 0 | 0 | 0.0000 |匿名[32],匿名[41] -- n | (n)-[:*..2]->() | | | +----------------+------+---------+------------- --+--------------------+----------+---- ---------------------+---------------------------- -------------------------------------------------- ---------------------------------+ | +过滤器 | 0 | 1 | 6 | 0 | 0 | 0.0000 | n | n.name = { AUTOSTRING0}; GetDegree(变量(n),一些(RelTypeName(KNOWS)),OUTGOING)> 0 | | | +----------------+------+---------+------------- --+--------------------+----------+---- ---------------------+---------------------------- -------------------------------------------------- ---------------------------------+ | +NodeByLabelScan | 4 | 4 | 5 | 0 | 0 | 0.0000 | n | :船员 | +------------------------+----------------+------+- --------+-----------------+--------+--- -------------------+----------------------------+- -------------------------------------------------- -------------------------------------------------- --------+

这应该可以帮助您:

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

【讨论】:

  • 感谢您解释应用过滤器的顺序。我需要查看解释计划以进一步了解它。
猜你喜欢
  • 1970-01-01
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 2014-06-14
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 2015-06-27
相关资源
最近更新 更多