【问题标题】:Cypher: How to match relationship-node-relationship within a pathCypher:如何在路径中匹配关系节点关系
【发布时间】:2015-10-31 02:53:07
【问题描述】:

我是 Cypher 和 Neo4j(以及 Stack Overflow)的新手,所以希望这个问题有一个简单的答案。我花了几个小时阅读文档和谷歌搜索,但没有找到确切的答案来回答这个问题。

显然我需要更多的声望来发布图片,所以我会尽力使用文字。

我可以像这样找到从一个节点到另一个节点的路径:

    MATCH path = (a {name:"a"})-[*]-(x {name:"x"})
    RETURN extract(r IN nodes(path) | r);

这可能会返回如下两条路径:

    (a)-[:RED]->(b)<-[:BLUE]-(c)-[:RED]->(f)<-[:RED]-(g)-[:BLUE]->(h)<-[:RED]-(x)

    (z)-[:RED]->(h)<-[:RED]-(x)

到目前为止一切顺利。当然,数据库中还有很多其他关系和节点连接到这些节点,但这是正确的路径。

我需要沿着路径找到一个节点,其中有两个 RED 关系进入,如下所示:

    -[:RED]->(findme)<-[:RED]-

在上面的两个路径示例中,findme = (f) 和 (h)。

注意:数据库中会有很多匹配项,但我只想要路径中的一个(应该只有一个)。此外,路径中可能有许多节点和不同的关系,或者只有 3 个节点,每个节点都通过 RED 关系连接。

我尝试使用匹配:

    MATCH (a)-[*]-(b)-[:RED]->(findme)<-[:RED]-(c)-[*]-(x) RETURN findme;

只要有至少 5 个节点就可以工作,但不适用于 3 个节点。

如何在路径中找到这种模式匹配?

【问题讨论】:

  • “红色”关系是否必须是路径的一部分,或者“findme”节点在路径上就足够了,“红色”关系来自路径外的节点?
  • 旁注:您在 return 子句中进行的提取似乎无关紧要。除非您对节点做更多的事情而不是将它们拉出路径,否则您可以直接RETURN nodes(path)。
  • @jjaderberg,是的,“红色”节点必须在路径上。很抱歉没有澄清这一点。另外,感谢有关返回节点(路径)的提示。我不知道该命令也会返回关系。非常好!

标签: neo4j cypher


【解决方案1】:

你很接近!如您所知,* 表示可变长度/深度。您可以像在查询中那样单独使用该符号,也可以指定一个范围。如果没有指定范围,* 表示“一个或多个”。如果您应用上一个查询

MATCH (a)-[*]-(b)-[:RED]->(findme)<-[:RED]-(c)-[*]-(x)
WHERE a.name = "a" AND x.name = "x"
RETURN findme

到三个节点的路径

(a)-[:RED]->(findme)<-[:RED]-(x)

路径中的两个关系可能已被查询的非变量部分匹配。但是没有任何关系可供可变部分匹配。 (a)-[*]-(b) 和 (c)-[*]-(x) 部分都需要“一个或多个”,但还有零个关系需要匹配。

您可以将* 的含义更改为“零或更多”,方法是将其明确指定为一个范围。这样,当路径中没有关系时,查询的两个变量部分也将匹配。

MATCH (a)-[*0..]-(b)-[:RED]->(findme)<-[:RED]-(c)-[*0..]-(x)
WHERE a.name = "a" AND x.name = "x"
RETURN findme

此查询将匹配仅包含您正在查找的“红色三元组”的路径,以及在三元组的一侧或两侧具有延伸关系的路径。

值得注意的是,具有“零或多个”范围匹配“零情况”的模式将在模式中具有两个标识符,但只有一个节点。因此,该节点绑定到两个标识符。对于上面模式左侧的标识符,当它匹配三节点路径时,说

节点a和节点b通过零深度关系连接

真的是很傻的说法

a和b是同一个节点

您可以查看this console,它在(a {name: "a"}) 和(x {name: "x"}) 之间有一个五节点路径,在(a {name: "a2"}) 和(x {name: "x2"}) 之间有一个三节点路径。相同的模式将匹配这两个路径(只需更改WHERE 子句中name 的值)。您将获得两条路径的五列,因为查询返回五个标识符。在三节点路径的情况下,第一个结果列将与第二个相同,第四个与第五个相同——因为 “节点a 和节点b 以零深度关系连接" 只是表示"a 和b 是同一个节点"。

【讨论】:

  • 感谢您非常详细的回复。我需要的一条信息是“当它匹配三节点路径时,说节点a和节点b以零深度关系连接真的是说a和b是同一个节点的愚蠢方式。" 非常感谢!
【解决方案2】:

这个怎么样:

MATCH p=(a {name:"a"})-[*]-(x {name:"x"})
WITH nodes(p) AS nodes
UNWIND nodes AS n
WITH n WHERE exists(()-[:RED]->(n)<-[:RED]-())
RETURN n
  1. MATCH 在从 a 到 x 的路径上。
  2. 获取路径中的所有节点
  3. 对于路径中的每个节点,过滤我们有两个传入 RED 关系的节点

【讨论】:

  • 如果“红色”关系必须是路径的一部分(不确定这是否是要求),您也需要检查它,对吗?就目前而言,查询还将返回路径上的节点,这些节点具有来自路径外节点的传入“红色”关系。
  • @William Lyon 感谢您提供有关 UNWIND 的提示,它似乎在路径上的每个节点上运行。在这种情况下,我需要 RED 关系沿着路径(抱歉没有指定),但您的答案将来可能会派上用场。我很好奇是否有办法修改答案以确保 RED 关系在路径中?
【解决方案3】:

我喜欢有多个答案可以完成这项工作:)

这是我的:

MATCH path=(a {name:"a"})-[*]-(x {name:"x"})
RETURN filter(x in nodes(p) WHERE size((x)<-[:RED]-()) = 2) as n

为威尔和乔纳森+1

【讨论】:

  • +1 是的,尺寸很可爱!但是,当“红色”关系不是路径的一部分时,此查询也会匹配,对吗?我不确定操作是否需要,或者红色是否应该包含在从 a 到 x 的路径中。
  • @ChristopheWillemsen “大小”的答案非常聪明。我以前没见过。在这种情况下,我需要 RED 关系沿着路径(抱歉没有指定)。您的答案是否有可能包含此约束的修改?
  • @BradStone 不是可以打败乔纳森的回答 :) 但是,我建议加入 neo4j 松弛用户频道,如果这种查询是你需要经常做的事情,我会请你谈谈我们关于您的模型以及我们如何帮助您改进它 - 我的意思是性能方面,这并不是我们在生产中倾向于执行的最佳查询
  • @ChristopheWillemsen,感谢您的提示。我现在在 neo4j-users 松弛组。随着我获得更多经验,性能调整将变得很重要。顺便说一句,您是否建议加入特定的频道?
  • 是的帮助建模和一般问题的帮助密码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 2023-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多