Neo4J Cypher:按条件过滤可变长度路径
Neo4J Cypher: filter out variable length paths by criteria
我如何暗示对可变长度路径的限制?
我有一些 start
节点查询的所有可能路径:
CREATE INDEX ON :NODE(id)
MATCH all_paths_from_Start = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
RETURN paths;
不,我想过滤掉至少有两个人具有相同 country
的所有路径。 我该怎么做?
我能想到的一个解决方案是获得同一个国家/地区的 nodes
of the path, and for each person on the path, extract
the value of the number of persons from the same country (which we determine by filter
ing。如果来自同一国家/地区的人数为零,则一条路径包含来自不同国家/地区的人员,即对于所有人,只有一个人(himself/herself)来自该国家/地区。
MATCH p = (start:Person {id: 128})-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.country <> "Uganda"
WITH p, nodes(p) AS persons
WITH p, extract(p1 IN persons | size(filter(p2 IN persons WHERE p1.country = p2.country))) AS personsFromSameCountry
WHERE length(filter(p3 IN personsFromSameCountry WHERE p3 > 1)) = 0
RETURN p
该查询在语法上是正确的,但我没有在任何数据上对其进行测试。
请注意,我将 id = 128
条件移至模式并将 all_paths_from_Start
变量缩短为 p
。
1) 获取一组国家到可能重复的路径:REDUCE
2) 删除重复项并比较数组的大小:UNWIND
+ COLLECT(DISTINCT...)
MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
WITH path,
REDUCE(acc=[], n IN NODES(path) | acc + n.country) AS countries
UNWIND countries AS country
WITH path,
countries, COLLECT(DISTINCT country) AS distinctCountries
WHERE SIZE(countries) = SIZE(distinctCountries)
RETURN path
P.S。 REDUCE
可以替换为 EXTRACT
(感谢 Gabor Szarnyas):
MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
WITH path,
EXTRACT(n IN NODES(path) | n.country) AS countries
UNWIND countries AS country
WITH path,
countries, COLLECT(DISTINCT country) AS distinctCountries
WHERE SIZE(countries) = SIZE(distinctCountries)
RETURN path
P.P.S。再次感谢 Gabor Szarnyas 提供的另一个简化查询的想法:
MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
WITH path
UNWIND NODES(path) AS person
WITH path,
COLLECT(DISTINCT person.country) as distinctCountries
WHERE LENGTH(path) + 1 = SIZE(distinctCountries)
RETURN path
我如何暗示对可变长度路径的限制?
我有一些 start
节点查询的所有可能路径:
CREATE INDEX ON :NODE(id)
MATCH all_paths_from_Start = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
RETURN paths;
不,我想过滤掉至少有两个人具有相同 country
的所有路径。 我该怎么做?
我能想到的一个解决方案是获得同一个国家/地区的 nodes
of the path, and for each person on the path, extract
the value of the number of persons from the same country (which we determine by filter
ing。如果来自同一国家/地区的人数为零,则一条路径包含来自不同国家/地区的人员,即对于所有人,只有一个人(himself/herself)来自该国家/地区。
MATCH p = (start:Person {id: 128})-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.country <> "Uganda"
WITH p, nodes(p) AS persons
WITH p, extract(p1 IN persons | size(filter(p2 IN persons WHERE p1.country = p2.country))) AS personsFromSameCountry
WHERE length(filter(p3 IN personsFromSameCountry WHERE p3 > 1)) = 0
RETURN p
该查询在语法上是正确的,但我没有在任何数据上对其进行测试。
请注意,我将 id = 128
条件移至模式并将 all_paths_from_Start
变量缩短为 p
。
1) 获取一组国家到可能重复的路径:REDUCE
2) 删除重复项并比较数组的大小:UNWIND
+ COLLECT(DISTINCT...)
MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
WITH path,
REDUCE(acc=[], n IN NODES(path) | acc + n.country) AS countries
UNWIND countries AS country
WITH path,
countries, COLLECT(DISTINCT country) AS distinctCountries
WHERE SIZE(countries) = SIZE(distinctCountries)
RETURN path
P.S。 REDUCE
可以替换为 EXTRACT
(感谢 Gabor Szarnyas):
MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
WITH path,
EXTRACT(n IN NODES(path) | n.country) AS countries
UNWIND countries AS country
WITH path,
countries, COLLECT(DISTINCT country) AS distinctCountries
WHERE SIZE(countries) = SIZE(distinctCountries)
RETURN path
P.P.S。再次感谢 Gabor Szarnyas 提供的另一个简化查询的想法:
MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
WITH path
UNWIND NODES(path) AS person
WITH path,
COLLECT(DISTINCT person.country) as distinctCountries
WHERE LENGTH(path) + 1 = SIZE(distinctCountries)
RETURN path