Neo4j:如何 return 为具有多重关系的每对节点创建一条路径
Neo4j: How to return a single path for each pair of nodes that have multiple relationships
假设这样的图表:
(感谢https://neo4j.com/blog/neo4j-2-0-ga-graphs-for-everyone/)
(未显示但假设所有国家、所有艺术家和所有录音合同都在图中)
CYPHER 的用途是什么:
- 从英国开始,return每个至少有一份录制合同的国家都有一条路径
- 哪个路径是return并不重要,只是它是一条路径
- 应该return
(United Kingdom)<-[]-(Iron Maiden)-[]->(Epic)-[]->(United States)
,而不是(United Kingdom)<-[]-(Hybrid Theory)-[]->(Mad Decent)-[]->(United States)
或(United Kingdom)<-[]-(Iron Maiden)-[]->(Columbia)-[]->(United States)
,例如
- Return 任何 两个相连的国家/地区中的每一个国家/地区都有一条路径
- 应该 return 一条路径用于
(United Kingdom)-[]-(United States)
,一条路径用于 (Japan)-[]-(Canada)
,等等。 奖励积分 LIMIT 20
将其限制为 20 条路径或20个国家节点
- 哪个路径return也没关系,只是它是一个路径
编辑:我尝试了 MATCH (c1:Country)-[]-(c2:Country)
、MATCH p=((c1:Country)-[]-(c2:Country))
、WITH
和 UNWIND
的各种组合。我也尝试过使用 FOREACH
到 return 只有一条路径,但公式不太正确。
如果您使用子查询(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)
,您可能不希望 return两个都。所以我们对图表 ID 进行了限制,只有其中一个符合限制,镜像结果被过滤掉。
我们使用 RETURN other, collect(path)[0] as path
为每个国家和其他节点获取一条路径。请记住,这是在每个国家/地区节点调用的子查询中发生的,因此即使此处不存在 country
,也会针对特定国家/地区节点执行此操作。
当我们聚合时(比如这个collect(path)
,分组键(通常是非聚合变量)变得不同,所以对于国家和另一个国家,这将收集它们之间的所有路径然后选择路径列表中的第一条,这样我们就得到了两个不同国家之间的单一路径。
我们将子查询结果限制为 20,因为我们总共知道我们不想要超过 20 条路径,所以每个国家/地区我们也不想要超过 20 条路径。对于这种情况,这可能有点多余,但是当查询更复杂时,这是确保您没有做超出需要的工作的正确方法。
我们在子查询之外还有另一个 LIMIT,这样如果只处理几个国家,每个国家有几条路径,总路径不会超过 20。
假设这样的图表:
(感谢https://neo4j.com/blog/neo4j-2-0-ga-graphs-for-everyone/)
(未显示但假设所有国家、所有艺术家和所有录音合同都在图中)
CYPHER 的用途是什么:
- 从英国开始,return每个至少有一份录制合同的国家都有一条路径
- 哪个路径是return并不重要,只是它是一条路径
- 应该return
(United Kingdom)<-[]-(Iron Maiden)-[]->(Epic)-[]->(United States)
,而不是(United Kingdom)<-[]-(Hybrid Theory)-[]->(Mad Decent)-[]->(United States)
或(United Kingdom)<-[]-(Iron Maiden)-[]->(Columbia)-[]->(United States)
,例如
- Return 任何 两个相连的国家/地区中的每一个国家/地区都有一条路径
- 应该 return 一条路径用于
(United Kingdom)-[]-(United States)
,一条路径用于(Japan)-[]-(Canada)
,等等。 奖励积分LIMIT 20
将其限制为 20 条路径或20个国家节点 - 哪个路径return也没关系,只是它是一个路径
- 应该 return 一条路径用于
编辑:我尝试了 MATCH (c1:Country)-[]-(c2:Country)
、MATCH p=((c1:Country)-[]-(c2:Country))
、WITH
和 UNWIND
的各种组合。我也尝试过使用 FOREACH
到 return 只有一条路径,但公式不太正确。
如果您使用子查询(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)
,您可能不希望 return两个都。所以我们对图表 ID 进行了限制,只有其中一个符合限制,镜像结果被过滤掉。
我们使用 RETURN other, collect(path)[0] as path
为每个国家和其他节点获取一条路径。请记住,这是在每个国家/地区节点调用的子查询中发生的,因此即使此处不存在 country
,也会针对特定国家/地区节点执行此操作。
当我们聚合时(比如这个collect(path)
,分组键(通常是非聚合变量)变得不同,所以对于国家和另一个国家,这将收集它们之间的所有路径然后选择路径列表中的第一条,这样我们就得到了两个不同国家之间的单一路径。
我们将子查询结果限制为 20,因为我们总共知道我们不想要超过 20 条路径,所以每个国家/地区我们也不想要超过 20 条路径。对于这种情况,这可能有点多余,但是当查询更复杂时,这是确保您没有做超出需要的工作的正确方法。
我们在子查询之外还有另一个 LIMIT,这样如果只处理几个国家,每个国家有几条路径,总路径不会超过 20。