这是一个很好的问题,我很乐意提出答案。我将逐步介绍我的解决方案。首先,这是我正在测试的示例数据:
CREATE
(Global:Region {name:'Global'}),
(US:Region {name:'US'}),
(EU:Region {name:'EU'}),
(UK:Region {name:'UK'}),
(SE:Region {name:'SE'}),
(Global)-[:CONTAINS]->(EU),
(Global)-[:CONTAINS]->(US),
(EU)-[:CONTAINS]->(UK),
(EU)-[:CONTAINS]->(SE),
(Movie1:Movie {name:'Movie 1'}),
(Movie2:Movie {name:'Movie 2'}),
(Release1:Release {name:'Release 1'}),
(Release2:Release {name:'Release 2'}),
(Release3:Release {name:'Release 3'}),
(Release4:Release {name:'Release 4'}),
(Movie1)-[:HAS_RELEASE]->(Release1)-[:HAS_REGION]->(EU),
(Movie1)-[:HAS_RELEASE]->(Release2)-[:HAS_REGION]->(Global),
(Movie2)-[:HAS_RELEASE]->(Release3)-[:HAS_REGION]->(UK),
(Movie2)-[:HAS_RELEASE]->(Release4)-[:HAS_REGION]->(US);
这是我的解决方案...
MATCH p = (m:Movie)-[:HAS_RELEASE]->(:Release)-[:HAS_REGION]->(:Region)-[:CONTAINS*0..]->(:Region {name:'UK'})
WITH m, p
ORDER BY LENGTH(p)
WITH m, HEAD(COLLECT(p)) AS path
RETURN m.name AS Movie, [x IN NODES(path) WHERE x:Release | x.name] AS Release;
...产生:
Movie Release
Movie 1 Release 1
Movie 2 Release 3
好的,让我们逐步完成这个查询。第一部分……
MATCH p = (m:Movie)-[:HAS_RELEASE]->(:Release)-[:HAS_REGION]->(:Region)-[:CONTAINS*0..]->(:Region {name:'UK'})
...匹配包含英国地区(任何长度)的任何地区发行的电影。请注意*..0 表示我们仍在英国捕获版本,因为那将是一个 0 长度的步骤。
然后,对于每部电影,我们希望按路径长度排序,因为对于具有多条路径的电影(如电影 1),我们希望最短路径排在第一位...
WITH m, p
ORDER BY LENGTH(p)
...因为我们只想收集和保留最直接到英国节点的路径(这是集合中的第一条路径,因为我们按路径长度升序排序):
WITH m, HEAD(COLLECT(p)) AS path
现在我们为每部电影设置了一条路径。最后一行使用 EXTRACT 和 FILTER 的组合从每个路径中获取 Release 节点名称:
RETURN m.name AS Movie, [x IN NODES(path) WHERE x:Release | x.name] AS Release