Cypher 查询以验证有序列表中的所有项目是否由图中具有指定关系的节点按顺序表示

问题描述 投票:0回答:1

我正在为一个简单的文件系统建模,包含文件夹和文件。

(:Folder)<-[:IS_IN *]-(:Folder)<-[:IS_IN]-(:File)

用户可以给我任意路径,

/foo/bar/baz.txt
。在这种情况下,图表看起来像:

(:Folder {Name: '/'})<-[:IS_IN]-(:Folder {Name: 'bar'})<-[:IS_IN]-(:File {Name: 'baz.txt'})

在不知道用户将提供多长路径的情况下,是否有一种好的方法来查询给定路径是否在图中表示?如果我将路径拆分为文件夹名称的有序列表,我是否可以编写一个查询,当且仅当它们以与列表相同的顺序存在时返回节点?

天真地我可以用每个节点动态生成一个查询,但我宁愿不生成动态查询。

neo4j cypher
1个回答
0
投票

假设你传递了这个

$path
参数,并且路径中的最后一个元素是一个文件:

"/foo/bar/baz.txt"

假设你的数据是这样的:

(:Folder {Name: '/'})<-[:IS_IN]-
  (:Folder {Name: 'foo'})<-[:IS_IN]-
    (:Folder {Name: 'bar'})<-[:IS_IN]-
      (:File {Name: 'baz.txt'})

这应该有效:

WITH SPLIT($path, '/') AS p
WITH REVERSE(CASE WHEN p[0] = '' THEN ['/']+p[1..] ELSE p END) AS names
OPTIONAL MATCH (file:File {Name: names[0]})
RETURN REDUCE(s=file, n IN names[1..] |
  CASE WHEN s IS NOT NULL THEN [(s)-[:IS_IN]->(f1 {Name: n})|f1][0] END
) IS NOT NULL AS found

查询会返回是否找到

$path
中的路径

它将 $path 字符串分解为文件夹和文件名数组,将其反转,然后可选地匹配文件节点。我们使用 OPTIONAL MATCH,以便查询始终返回一个值,即使未找到文件。然后我们使用 REDUCE 函数循环遍历路径中的剩余文件夹,以验证每个需要的关系是否存在。我们使用 pattern comprehension 在循环中执行匹配。

© www.soinside.com 2019 - 2024. All rights reserved.