使用Neo4J中的密码来有效匹配子树的方法吗?

时间:2015-07-23 09:22:49

标签: neo4j cypher

如果我有一个在Neo4J中建模的树,并且我知道可能的子树的所有索引节点属性,我怎样才能快速进行匹配以确认该子树是否存在?

对于一个易于理解的例子,如果我的树是磁盘上所有目录和文件的表示,而我想要确认的是文件的存在,这就是我现在正在做的测试if / a / b / c / d / e / f / g / h / i / j / k / file.txt存在于一个图表中,其中我的文件系统节点具有标签mylabel并具有索引的basename属性:

MATCH (root:`mylabel` { basename: '/' })-[:contains]->(`1`:`mylabel` { basename: 'a' })-[:contains]->(`2`:`mylabel` { basename: 'b' })-[:contains]->(`3`:`mylabel` { basename: 'c' })-[:contains]->(`4`:`mylabel` { basename: 'd' })-[:contains]->(`5`:`mylabel` { basename: 'e' })-[:contains]->(`6`:`mylabel` { basename: 'f' })-[:contains]->(`7`:`mylabel` { basename: 'g' })-[:contains]->(`8`:`mylabel ` { basename: 'h' })-[:contains]->(`9`:`mylabel ` { basename: 'i' })-[:contains]->(`10`:`mylabel` { basename: 'j' })-[:contains]->(`11`:`mylabel` { basename: 'k' })-[:contains]->(leaf:`vdp`:`mylabel` { basename: 'file.txt' }) RETURN leaf

我也碰巧在叶子节点上有一个绝对路径属性,但我不能只搜索它,因为我想使用类似的查询来进行合并,如果我正在添加文件,以防万一file已移动(通过删除leaf与k的关系,并将leaf的新关系添加到某个其他目录节点),而不更新path属性。此外,我可以为不同的文件多次使用相同的绝对路径,因为它可以用于不同的磁盘(这是由具有包含磁盘名称的基本名称的根节点建模的,但在叶节点路径中看不到属性)。

上述查询需要2-7秒才能运行(未缓存)。有没有办法更快地做这样的事情?当我指定路径中的每个节点时,我希望Neo4J甚至可以处理长度为12 +的路径。

1 个答案:

答案 0 :(得分:1)

这里有一些想法:

  • 因为你总是从根节点开始(我假设只有一个)你在这里真的不需要索引。而是为根节点分配标签,例如Root并确保它是唯一带有该标签的节点
  • 有了这个,你可以提示Cypher我首先匹配根节点,然后在with
  • 之后进行路径匹配
  • 我假设您的层次结构中的子文件夹中的所有内容都有mylabel标签,因此在性能方面,最好跳过检查(因为它是隐含的)

MATCH (r:Root)
WITH r
MATCH (r)-[:contains]->(a { basename: 'a' })
-[:contains]->( { basename: 'b' })
-[:contains]->( { basename: 'c' })
-[:contains]->( { basename: 'd' })
-[:contains]->( { basename: 'e' })
-[:contains]->( { basename: 'f' })
-[:contains]->( { basename: 'g' })
-[:contains]->( { basename: 'h' })
-[:contains]->( { basename: 'i' })
-[:contains]->( { basename: 'j' })
-[:contains]->( { basename: 'k' })
-[:contains]->(leaf:`vdp`:`mylabel` { basename: 'file.txt' }) 
RETURN leaf

如果您事先不知道叶子的深度,可以使用可变路径长度匹配器:

match (r:Root)
with r
match p=(r)-[:contains*]->()
with p,[x in tail(nodes(p))|x.basename] as names
where names= ["a","b","c","d","e","f","g","h","i","j","k","file.txt"]
return p, names

但是,此语句将完全遍历您的while目录树,并且不会提前跳过。您可以使用例如在Java中使用遍历API。