首页 > 解决方案 > 首选通过直接连接而不是较长路径的节点

问题描述

我的图形模型应该允许从父级继承属性到子级,并覆盖子级的继承属性。属性是附加有HAS关系的节点。

CREATE (parent:Node {id: "P"})-[:HAS {inherited: true}]->(:Attribute:Name {value: "Indirect Name"})
CREATE (parent)-[:HAS]->(:Attribute:Other {value: "Other Attribute"})

CREATE (c1:Node {id: "C1"})-[:HAS]->(:Attribute:Name {value: "Direct Name"})
CREATE (c1)-[:BELONGS_TO]->(parent)
CREATE (c2:Node {id: "C2"})-[:BELONGS_TO]->(parent)

在这个例子中,我们有C1-[:BELONGS_TO]->PC2-[:BELONGS_TO]->PP定义了一个Name继承的属性和一个Other不继承的属性。C1已覆盖该Name属性,而C2继承该属性。

示例图

我现在想查找属于某个节点的所有相关属性:C1 的直接附加名称属性和 C2 的间接名称属性。不应为 C1 和 C2 考虑“其他”属性,因为它不是继承的。

要获取所有直接和继承的属性,我可以使用以下查询:

MATCH (c {id: "C1"})-[:HAS]->(directAttribute:Attribute), (c)-[]->(:Node)-[:HAS{inherited: true}]->(inheritedAttribute:Attribute) RETURN directAttribute, inheritedAttribute

但这显然会返回两个Name属性,一个来自C1和继承自P。我们如何“更喜欢”直接附加到节点的属性而不是继承的属性,以便在这种情况下,查询只返回“直接”名称属性?

标签: neo4jcyphergraph-databases

解决方案


使用节点标签来区分属性名称对于您的用例来说非常笨拙。我建议将属性名称改为属性名称。例如,nameother以下数据创建查询中(以及foo, 以显示如何具有多个继承属性):

CREATE (parent:Node {id: "P"})-[:HAS {inherited: true}]->(:Attribute {name: "Indirect Name", foo: "Bar"})
CREATE (parent)-[:HAS]->(:Attribute {other: "Other Attribute"})

CREATE (c1:Node {id: "C1"})-[:HAS]->(:Attribute {name: "Direct Name"})
CREATE (c1)-[:BELONGS_TO]->(parent)
CREATE (c2:Node {id: "C2"})-[:BELONGS_TO]->(parent)

然后,您可以使用方便的 APOC 函数apoc.map.merge来获取 a 的适用属性Node(注意将“直接”属性作为第二个参数传递)。

例如,如果您将此查询用于“C1”:

MATCH (c:Node {id: "C1"})
OPTIONAL MATCH (c)-[:HAS]->(da:Attribute)
OPTIONAL MATCH (c)-[:BELONGS_TO]->()-[:HAS {inherited: true}]->(ia:Attribute)
RETURN c, apoc.map.merge(ia, da) AS attrs

结果是:

╒═══════════╤══════════════════════════════════╕
│"c"        │"attrs"                           │
╞═══════════╪══════════════════════════════════╡
│{"id":"C1"}│{"name":"Direct Name","foo":"Bar"}│
└───────────┴──────────────────────────────────┘

“C2”的相同查询得到这个结果:

╒═══════════╤════════════════════════════════════╕
│"c"        │"attrs"                             │
╞═══════════╪════════════════════════════════════╡
│{"id":"C2"}│{"name":"Indirect Name","foo":"Bar"}│
└───────────┴────────────────────────────────────┘

您可能还想使用不同的关系类型(例如[:INHERITS])来代替[:HAS {inherited: true}]


推荐阅读