给出一个neo4j数据库,其中包含文件夹或叶类型的顶点。普通树是使用:childof关系建模的,并且有一个“根”节点,它是所有顶点的共同祖先。
在显示树时,我想根据文件夹类型的任何顶点的ID过滤掉全部分支。此外,还有一个用于过滤叶型顶点上所有属性的过滤器。棘手的部分是,我不想看到所有后代叶子节点都被过滤掉的文件夹。每个查询仅返回直接后代,但过滤器将应用于整个子树。查询必须返回直接子级,以及每个包含未过滤出叶子的文件夹的id的集合。
用例是一个API,用于显示基于某些过滤器约束的层次结构。我已经在API应用程序代码中对此进行了编程,但是将所有数据从数据库传输到API应用程序的速度太慢,因此我需要改进查询以压缩数据传输。第三种方法是使用专门构建的过程来执行此过滤,从而将树保留在内存中。这项工作已经取得了一些成功,但是如果可以的话,我更喜欢使用货架软件。
以下代码用于获取顶级节点,而不进行过滤。只有在至少有一个后代也匹配的情况下,我才努力表达MATCH
MATCH (p)-[:childof]->(s:Folder) WHERE s.name = 'root'
WITH p OPTIONAL MATCH (v)-[:childof*1..]->(p)
WHERE NOT((v)<-[:childof]-(:Folder))
RETURN p, collect(v.id) as folder_ids
我个人对此问题的倾向是,它对于通用图形引擎而言过于具体,但我希望能证明自己是错误的。
答案 0 :(得分:1)
听起来您很亲密。
我们可以在文件夹级别使用模式理解来检查符合过滤条件的子项,并确保仅保留至少具有一个符合过滤条件的子项的文件夹。
在直接后代级别上,如果我们使用MATCH而不是OPTIONAL MATCH,由于文件夹将为您过滤,因此剩下的唯一直接后代是至少具有这些文件夹之一的文件夹。
例如,假设我们的过滤器是叶子节点必须具有active = true
,所以我们要确保要考虑的文件夹必须至少有一个符合该过滤器的子节点,并且当我们返回到直接后代,我们只希望在合格文件夹的集合不为空的情况下保留该后代。
类似这样的东西:
MATCH (p)-[:childof]->(s:Folder) WHERE s.name = 'root'
WITH p
MATCH (folder)-[:childof*1..]->(p)
WHERE NOT((folder)<-[:childof]-(:Folder)) AND
size([(folder)<-[:childof]-(child) WHERE child.active = true | child]) <> 0
RETURN p, collect(folder.id) as folder_ids