【问题标题】:How to work with type hierarchies in Neo4j?如何在 Neo4j 中使用类型层次结构?
【发布时间】:2022-03-06 17:03:07
【问题描述】:

有没有办法在 Neo4j 中对类型层次结构进行建模?例如,如果我想构建汽车的类层次结构,我可能有一个基本类型“Car”,然后有扩展它的子类,如“SportCar”等。

我希望能够创建“SportCar”的实例,但运行查询以获取所有“Car”。这可能吗?如果有,技术是什么?

我认为我想要做的是创建一个“标签层次结构”——但我认为 neo4j 不支持这一点。

【问题讨论】:

  • 在阅读了有关 neo4j 的更多信息后,我学到的一件事是,实际上并没有“类型”系统。他们拥有的最接近的东西是他们所谓的“标签”,基本上只是可​​以放在节点上的“标签”。因此,导航层次结构是完全可行的,但您必须以更具体的方式构建查询,因为“类型”等没有开箱即用的支持。
  • AgensGraph(PostgreSQL fork 扩展了图形数据库功能)具有标签层次结构:agensgraph.com/agensgraph-docs/…

标签: inheritance graph neo4j polymorphism data-modeling


【解决方案1】:

保罗,

首先,我建议您阅读“图形数据库”,这是一本免费的 O'Reilly 电子书,地址为 this link

作为一个快速的答案,有很多方法可以做这种事情,最好的选择取决于你要解决的问题。一种方法是构造一个“Car”节点,然后将您的“SportCar”节点与“Car”节点相关联,并具有类似

的类型关系
CREATE (m:Car)
MATCH (m:CAR) WITH m CREATE (n:SportCar)-[:IS_A]->(m)

并创建其他类型的汽车,并将它们与 Car 节点相关联。

然后您可以通过

找到所有汽车
MATCH (m:Car)<-[:IS_A]-(n) RETURN n

您也可以只在每个节点上放置 Car 和 SportCar(以及 LuxoCar 等)标签。这只是众多方法中的两种。

恩典与和平,

吉姆

【讨论】:

  • 是的,我知道您可以在创建节点时应用“IsA”关系,但这不会让您执行“MATCH (c:Car) RETURN c”并取回所有汽车,包括作为 Car 子类的汽车。我只是不认为 neo4j 支持搜索中的继承。需要明确的是,OrientDB 确实支持这一点——我想这只是两个平台之间的关键区别。此外,标签方法无法扩展,并且在层次结构发生变化时管理起来会很麻烦——想象一下必须返回并更新所有以前的标签,等等。
【解决方案2】:

至少有两种方法可以做到这一点:

1) 为每个对象使用多个标签

CREATE(BMW325d:Car:PassengerCar:DieselCar)
CREATE(Porsche911:Car:SportsCar:...)

2) 创建本体

对类层次结构建模的第二种方法是使用本体。尽管 Neo4j 将数据建模为属性图,并且本体更适合 RDF 三重存储,但仍有一些方法可以使用它们。

您可以使用 Protégé(开源)创建本体。然后将本体保存在 .owl-File 中,并使用 Plugin 将其上传到 Neo4j。 之后,您将 Neo4j 中的节点声明到在 Protégé 中创建的 Metagraph。更详细的描述描述在here

关于这个主题的更多信息...

出于您的目的,RDF 三重存储是一个有趣的选择,尤其是如果您想为数据添加语义,例如使用推理和继承。我建议仔细查看 RDF Triple Stores,它们也是图形 - 但它们以三元组(主题 - 谓词 - 对象)而不是节点和关系存储数据。 Top Braid Composer 是一个“易于学习”的工具,可让您开始使用它们。

虽然,我希望 Property Graphs 和 RDF 三元存储之间的差距很快就会缩小,因为这是一个权衡。因此,在选择其中一个之前,您应该仔细设置您对数据库的要求。

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    所以我能想到的壁橱就是这个例子。

    第 1 步:创建汽车类型的类型层次结构。

    create (c:CarType{Code:"Car"})
    create (sc:CarType{Code:"SportCar"})
    create (sc)-[:SubCarOf]->(c)
    

    第 2 步:创建“SportCar”的实例并记录(通过关系属性)它是“CarType”。

    merge (sc:CarType{Code:"SportCar"})
    create (i:SportCar)
    create (i)-[:CarType]->(sc)
    

    第 3 步:编写一个查询,查找从“Car”派生的所有“CarType”以及任何仅属于“Car”类型的所有“CarType”,然后查找这些实例。

    match (c)-[:CarType]->(ct:CarType{Code:"Car"})
    return c as Car
    union
    match (sct)-[:SubCarOf*]->(ct:CarType{Code:"Car"}), 
    (c)-[:CarType]->(sct)
    return c as Car
    

    【讨论】:

      【解决方案4】:

      作曲

      您可以考虑组合来代替继承。

      CREATE (c0:Car:SportsCar {colour: "yellow", brand: "Bugatti", country: "France"}),
      (c1:Car:LuxuryCar {colour: "red", brand: "Mercedes-Benz", country: "Germany"})
      
      • 查找所有Cars
      MATCH (c:Car) RETURN c;
      

      • 查找所有SportCars:
      MATCH (c:Car:SportsCar) RETURN c;
      

      • 查找所有LuxuryCars:
      MATCH (c:Car:LuxuryCar) RETURN c;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-10
        • 2020-03-28
        • 1970-01-01
        相关资源
        最近更新 更多