微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Neo4j:如何为具有多个关系的每对节点返回单个路径

如何解决Neo4j:如何为具有多个关系的每对节点返回单个路径

假设一个图形如下:

(感谢 https://neo4j.com/blog/neo4j-2-0-ga-graphs-for-everyone/

(未显示,但假设所有国家、所有艺术家和所有录制合同都在图表中)

CYPHER 的用途是什么:

  • 从英国开始,为每个至少有一个录制合同的国家/地区返回一条路径
    • 返回哪个路径无关紧要,只是它是单个路径
    • 应该返回 (United Kingdom)<-[]-(Iron Maiden)-[]->(Epic)-[]->(United States),而不是 (United Kingdom)<-[]-(Hybrid Theory)-[]->(Mad Decent)-[]->(United States)(United Kingdom)<-[]-(Iron Maiden)-[]->(Columbia)-[]->(United States),例如
  • 为连接的任意两个国家/地区中的每一个返回一条路径
    • 应该为 (United Kingdom)-[]-(United States) 返回一条路径,为 (Japan)-[]-(Canada) 返回一条路径,等等。LIMIT 20 的奖励积分将其限制为 20 条路径或 20 个国家/地区节点
    • 也无关紧要返回哪个路径,只是它是单个路径

编辑:我尝试了 MATCH (c1:Country)-[]-(c2:Country)MATCH p=((c1:Country)-[]-(c2:Country))WITHUNWIND 的各种组合。我也尝试使用 FOREACH 只返回一个路径,但不能完全正确地使用公式。

解决方法

如果您使用子查询(Neo4j 4.1.x 或更高版本),这会更容易。那是因为子查询可以帮助将您需要执行的操作(在本例中为 collect() )扩展到每个国家/地区的单个国家/地区的扩展和工作,而不必在整个查询的所有行中执行它,这可能会给堆带来压力。

实际上,由于国家/地区的数量很少,所以不会有问题,但在处理较大的节点集时这是一个很好的方法。

MATCH (country:Country)
CALL {
 WITH country
 MATCH path = (country)<-[:FROM_AREA]-(:Artist)-[:RECORDING_CONTRACT]->(:Label)-[:FROM_AREA]->(other:Country)
 WHERE id(country) < id(other)
 RETURN other,collect(path)[0] as path
 LIMIT 20
}
RETURN country,path
LIMIT 20

让我们看看这是做什么的。 我们匹配到:国家节点。

每个国家/地区,我们都会匹配您正在寻找的模式。如果图中只有这些路径和标签,那么您可以省略模式中的标签,因为关系类型应该足以找到正确的节点。

WHERE id(country) < id(other) 用于防止镜像结果。例如,在查询过程中,如果我们从 (United Kingdom)-[*]-(United States) 找到一条路径,并且我们还找到了另一个方向的路径,对于 (United States)-[*]-(United Kingdom),您可能不想同时返回两者。因此,我们对图 id 设置了限制,以便其中只有一个满足限制,并且镜像结果会被过滤掉。

我们使用 RETURN other,collect(path)[0] as path 获取每个国家和其他节点的单个路径。请记住,这是在按国家/地区节点调用的子查询中发生的,因此即使此处不存在 country,也会针对特定国家/地区节点执行此操作。

当我们聚合时(比如用这个collect(path),分组键(通常是非聚合变量)变得不同了,所以对于这个国家和另一个国家,这将收集它们之间的所有路径,然后选择路径列表中的第一个,这样我们就得到了两个不同国家/地区之间的单一路径。

我们将子查询结果限制为 20,因为我们知道我们总共不想要超过 20 条路径,所以每个国家我们也不想要超过 20 条路径。对于这种情况,这可能有点多余,但是当查询更复杂时,这是确保您没有做超出需要的工作的正确方法。

我们在子查询之外还有另一个 LIMIT,这样如果只处理几个国家,每个国家有几条路径,总路径不会超过 20。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。