Neo4J 密码查询“继承”术语

Posted

技术标签:

【中文标题】Neo4J 密码查询“继承”术语【英文标题】:Neo4J cypher query for "inherited" terms 【发布时间】:2015-03-14 13:11:43 【问题描述】:

使用neo4j v2.1.7 的社区版,我正在创建代表许可证的节点。

每个许可都有条款,并且可以“继承”另一个许可的条款。许可证的本地条款会影响继承许可证中的相同条款。

我正在尝试编写一个匹配本地和继承术语的密码查询。

这更容易用一些代码来演示。

我创建了一个继承自另一个许可证的许可证:

create 
(l1:License)-[:inherits]->(l2:License),
(l1)-[:term]->(:Foovalue:"A"),
(l1)-[:term]->(:Larvalue:"C"),
(l2)-[:term]->(:Larvalue:"D"),
(l2)-[:term]->(:Barvalue:"B")

我想要一个查询来查找具有或继承以下术语的许可证:Foo = A、Bar = B、Lar = C

所以 l1 会匹配,因为它具有正确的 Lar 和 Foo 值,并继承了带有正确值的 Bar。

l2 不匹配,因为它没有正确的 Lar 并且缺少 Foo。

我尝试了以下,但看起来很麻烦,至少有两个问题:

    我添加了“可选匹配 (l1)-[:inherits]->(l2:License)”,因为我想匹配不继承其他许可条款的许可。但是,由于某种原因,我不明白,可选匹配给了我图表中的两个许可证节点。

    如何测试属性是否在范围内?换句话说,如果许可证的属性是像“20150101”这样的日期,我想测试 20140101 和 20140101 之间的值怎么办?由于我的“位置”是测试路径的存在,所以我看不到如何测试一个属性是大于还是小于另一个值。

密码查询不正确:

match (l1:License)
optional match (l1)-[:inherits]->(l2:License)
where 
( 
   (l1)-[:term]->(:Foovalue:"A") OR 
   (
       not((l1)-[:term]->(:Foovalue:"A"))
       and
       (l2)-[:term]->(:Foovalue:"A")
   )
)
AND
(
   (l1)-[:term]->(:Barvalue:"B") or 
   (   
      not((l1)-[:term]->(:Barvalue:"B"))
      and 
      (l2)-[:term]->(:Barvalue:"B")
    )
)
AND
(
   (l1)-[:term]->(:Larvalue:"C") or 
   (
      not((l1)-[:term]->(:Larvalue:"C")) and
      (l2)-[:term]->(:Larvalue:"C")
   )
)
return count(l1)

提前致谢!

【问题讨论】:

【参考方案1】:

我认为您仍然在关系方面考虑太多,您的查询看起来像很多连接。

我认为这样就足够了。

// find the 3 terms
MATCH (t1:Foo value:"A"),(t2:Bar value:"B"), (t3:Lar value:"C")
UNWIND [t1,t2,t3] as term
// use them as starting point
MATCH path = (l:License)-[:INHERITS*0..]->(l2)-[:TERM]->(term)
RETURN l,l2,term, path

【讨论】:

这非常接近,但我正在努力弥合差距。此解决方案没有解决术语隐藏继承术语的情况。换句话说,如果一个许可证具有 Foovalue:"D" 但继承了另一个许可证其中 Foovalue:"A",那么它仍然会在路径中返回。我想检查许可证以查看它们是否包含与所需值不匹配的条款。如果他们这样做,那么他们应该被过滤掉。如果它们没有带有错误值的术语,那么我知道它们应该被返回,因为它们必须继承正确的术语。 这似乎有效:MATCH (t1:Foo value:"A"),(t2:Bar value:"B"), (t3:Lar value:"C") UNWIND [t1,t2,t3] as term MATCH path = (l:License)-[:inherits*0..]->(l2)-[:term]->(term) where ( ((l)-[:term]->(:Foovalue:"A") OR NOT((l)-[:term]->(:Foo))) AND etc for bar and lar ) return l 一个问题如何过滤 t3 以获取介于 A 和 D 之间的值? filter (t in collect(t3) where t.value > "A" and t.value <= "Z") as t3f UNWIND [t1,t2,t3f] as term 在最终匹配中导致异常:类型不匹配:术语已定义且类型冲突

以上是关于Neo4J 密码查询“继承”术语的主要内容,如果未能解决你的问题,请参考以下文章

Neo4j 图中的密码查询

neo4j 密码查询优化

Neo4j 密码查询以获取与特定其他节点没有关系的所有节点

在 neo4j 密码查询中使用多个匹配子句不会返回任何结果

在庞大的数据集上优化 Neo4j 密码查询

如何在 neo4j .net 客户端中使用密码查询返回两个集合