如何要求 Neo4j 考虑周期

2024-01-11

Neo4j 似乎故意省略了循环,因此查询如下:

MATCH (n1)-[:R]->(n2)<-[:R]-(n1)
RETURN n1, n2;

除非存在两个类型关系,否则始终不返回任何内容R之间n1 and n2(这绝对是可能的,而且是一个糟糕的黑客)。

但我有一个场景,这个循环可能会发生并且是期望的:

MATCH (n1)-[:R]->(n2)<-[:R]-(n3)
RETURN n1, n2, n3;

在这个查询中,n1 and n3可能是相同的节点或不同的节点,这一切都取决于数据(两者都是有效的)。实现此目的的一种方法如下:

MATCH (n1)-[:R]->(n2)
MATCH (n2)<-[:R]-(n3)
RETURN n1, n2, n3;

最后一个查询将包括所有路径,甚至循环,这完全没问题。但我的情况比这更复杂:

MATCH (n0)
OPTIONAL MATCH (n0)-[:R0]->(n1)-[:R]->(n2)<-[:R]-(n3)
RETURN n0, n1, n2, n3;

正如我们之前所见,此查询中省略了循环,因此我们必须将其分解为两个OPTIONAL MATCHes:

MATCH (n0)
OPTIONAL MATCH (n0)-[:R0]->(n1)-[:R]->(n2)
OPTIONAL MATCH (n2)<-[:R]-(n3)
RETURN n0, n1, n2, n3;

但这和以前不一样(如果另一个有效的话)。这里是第二个OPTIONAL MATCH当第一个路径返回时,可能不会返回任何路径。换句话说,两人OPTIONAL MATCHes 是独立的。

所以我的问题是:如何实现以下查询并获取结果中的周期?

MATCH (n0)
OPTIONAL MATCH (n0)-[:R0]->(n1)-[:R]->(n2)<-[:R]-(n3)
RETURN n0, n1, n2, n3;

我希望它不会太混乱!

Why two OPTIONAL MATCHes 不是答案

考虑以下节点和关系:

  1. CREATE (n0:S)-[:R]->(n1:R)<-[:R]-(n2:E)-[:R]->(n3:R:L);
  2. CREATE (n0:S)-[:R]->(n1:R:L)<-[:R]-(n2:E);
  3. CREATE (n0:S)-[:R]->(n1:R)<-[:R]-(n2:E);

在上面的示例中,以下是标签的含义(以便您能够理解问题):

  • :S起始节点
  • :R修订
  • :E entity
  • :L最新版本与最新版本相同

在此示例中,每条数据记录都表示为:E+:R当记录更新时,一个新的:R被添加到其中。数据的当前状态被标记:L这样我们就可以找到最新的版本。

现在,在给定的三个示例中,最后一个是无效数据,因为它没有任何数据:L。第一个有两次修订,第二个有一次。

请求的查询应该:

  1. Return :S不管
  2. 返回所有实体及其最新修订版(仅当它们具有最新修订版时)
  3. 没有最新修订的实体是没有意义的,根本不应该返回

如果 Neo4j 支持循环,此查询将返回请求的数据:

MATCH (n1:S)
OPTIONAL MATCH (n1)-[:R]->(n2:R)<-[:R]-(n3:E)-[:R]->(n4:R:L)
RETURN labels(n1), labels(n3), labels(n4);

The 预期成绩对于上面的查询是:

╒════════════╤════════════╤════════════╕
│"labels(n1)"│"labels(n3)"│"labels(n4)"│
╞════════════╪════════════╪════════════╡
│["S"]       │["E"]       │["R","L"]   │
├────────────┼────────────┼────────────┤
│["S"]       │["E"]       │["R","L"]   │
├────────────┼────────────┼────────────┤
│["S"]       │null        │null        │
└────────────┴────────────┴────────────┘

But the 实际结果 are:

╒════════════╤════════════╤════════════╕
│"labels(n1)"│"labels(n3)"│"labels(n4)"│
╞════════════╪════════════╪════════════╡
│["S"]       │["E"]       │["R","L"]   │
├────────────┼────────────┼────────────┤
│["S"]       │null        │null        │
├────────────┼────────────┼────────────┤
│["S"]       │null        │null        │
└────────────┴────────────┴────────────┘

正如您所看到的,第二条路径被缩短,因为它包含一个循环。现在如果我们使用这两个OPTIONAL MATCH方法:

MATCH (n1:S)
OPTIONAL MATCH (n1)-[:R]->(n2:R)<-[:R]-(n3:E)
OPTIONAL MATCH (n3)-[:R]->(n4:R:L)
RETURN labels(n1), labels(n3), labels(n4);

结果将是:

╒════════════╤════════════╤════════════╕
│"labels(n1)"│"labels(n3)"│"labels(n4)"│
╞════════════╪════════════╪════════════╡
│["S"]       │["E"]       │["R","L"]   │
├────────────┼────────────┼────────────┤
│["S"]       │["E"]       │["R","L"]   │
├────────────┼────────────┼────────────┤
│["S"]       │["E"]       │null        │
└────────────┴────────────┴────────────┘

虽然第二种情况已得到解决,但第三种情况现在是问题所在,因为这两个可选子句可以独立存在。

抱歉问了这么长的问题,我试着简短一点!


如果我正确理解了这个问题,这个查询应该为您提供您正在寻找的预期结果表:

MATCH (n1:S)
OPTIONAL MATCH (n1)-[:R]->(n2:R)<-[:R]-(n3:E)
WHERE (n3)-[:R]->(:R:L)
OPTIONAL MATCH (n3)-[:R]->(n4:R:L)
RETURN labels(n1), labels(n3), labels(n4)

关键是我们给第一个可选匹配的 WHERE。可选匹配仅在以下情况下才会匹配n3有所需的路径:R:L节点,并且它将计算 OPTIONAL MATCH 已经遍历的关系和节点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何要求 Neo4j 考虑周期 的相关文章

随机推荐