【问题标题】:Neo4j would I need repeated nodes or can I reuse the same ones?Neo4j 我需要重复节点还是可以重复使用相同的节点?
【发布时间】:2017-12-30 19:15:04
【问题描述】:

我的任务是研究 Neo4j 以满足我们的业务需求。我创建了一些非常小的图表来习惯密码语法。

我们有一个场景,用户可以通过许多选项进行搜索,然后需要显示他们的相关数据并在过滤结果时跟踪这些可用的库存商品。作为一个简单的例子(但与我们需要的设计相同)。我们可能有 4 件衣服(T 恤、毛衣、牛仔裤、衬衫),用户可以选择其中任何一件来显示它们的尺寸和颜色等,并跟踪库存数量。然而,用户应该能够首先选择尺寸或颜色,而不是显示不同的物品(T 恤、牛仔裤等)。基本上不同的组合取决于选择什么。

牛仔裤(库存 20 件)> 红色 (6) > 小号 (2) 或大号 (4),牛仔裤 > 绿色 > 小号或大号,小号 > 红色 > T 恤、衬衫、绿色 > 大号 > T 恤

在这种情况下,是否需要为每个项目重复颜色和大小节点,或者我可以只创建一次并重复使用它们吗?这是我有点困惑的事情。对于一个选项节点,我们可能会有 150 多个(国家列表)选项,如果每个选项节点都有其自己的唯一节点(但对于其他选项作为新节点重复),那是否有很多重复项?我们可以拥有一百万多个节点...

对不起,如果这是一个愚蠢的问题!只是想收集一下 Neo4j 中是否有处理这种用例的特定方法。

非常感谢您的帮助和建议。 :)

【问题讨论】:

    标签: database search neo4j tree cypher


    【解决方案1】:

    本质上,这个问题可以追溯到 ER 建模中的好旧属性与实体问题

    1. 使用单独的实体。为颜色、大小、国家等创建单例节点似乎是一个可行的解决方案,您可以将它们重用于多个项目。例如,如果您想将红色分配给项目n,您将发出以下查询:MATCH (r:Color {name: 'red'} CREATE (n)-[:HAS_COLOR]->(r)。要选择所有红色节点,请使用MATCH (n:Item)-[:HAS_COLOR]->(:Color {name: 'red'})。这种方法可以很容易地选择所有可用的颜色,例如MATCH (c:Color) RETURN DISTINCT c

    2. 使用属性。使用属性也应该可以正常工作。过滤更容易(MATCH (:Item {color: 'red')),并且可以使用MATCH (n) RETURN DISTINCT n.color实现列出可用颜色

    总之,与大多数数据建模问题一样,您可能需要进行几次迭代才能正确构建数据模型,并且可能还需要进行一些基准测试/性能调整。幸运的是,Neo4j 可以很容易地尝试不同的数据模型。

    【讨论】:

    • 这太棒了,谢谢!所以我可以有效地拥有一个以所有不同国家为属性的 Country 节点? IE。 CREATE (country:COUNTRY { uk: "UK", usa: "USA, france: "France" }) 等等?如果我对所有节点及其各自的属性执行此操作,这肯定会使数据模型更加简洁!基本上our app will be filtering these results dynamically when options are selected so it needs to be as fast as we can get it.
    • 您是否建议使用具有属性的节点作为枚举?这在纸上是可行的,但这绝对不是一个好习惯。这样做有什么好处? (将这些作为枚举存储在 Java 代码中)。
    • 我认为由于我们对 Neo4j 缺乏了解,我们的团队正在努力让事情变得简单,但我们当然不想遵循糟糕的设计。我想我的想法是让属性与用户可以在应用程序中选择的选项相匹配? IE。如果用户选择国家英国,那么我们将对其进行 MATCH 并在用户选择更多选项(颜色、项目、大小等)时继续添加到查询中,但我不确定性能影响会是什么。我们希望通过树遍历来过滤结果,然后在最后查询我们的 MemSQL 数据库以检索详细数据。
    • Neo4j 的属性图模型允许您存储数组,因此您可以使用CREATE (:Countries {countries: ['UK', 'USA', 'France']}) 创建可用语言的列表。不过,我不确定这是否有用——理想情况下,这不应该在数据库中。
    • 沿树查询是一个有趣的想法,因为这本质上是一个可以存储在图形数据库中的索引(如果出于性能原因需要)。但是,要使其正常工作,用户必须对所有项目遵循完全相同的步骤(例如,首先是尺寸,其次是颜色等)。这对您的用例来说是现实的吗?
    【解决方案2】:

    创建数据模型的方法通常有很多种,您必须权衡利弊并找出最有效的方法。

    考虑的一个方面,属性(属性)与实体,Gabor 详细介绍了。

    另一方面,仅考虑实体,是您是否要使用树结构,向下钻取到其属性由树中其上方的节点定义的特定项目,或者

    例如,你可能有一棵这样的树:

    (jeans:Clothing:Attribute{type:'jeans'})-[:COLOR]->(jeansColor:Color:Attribute{type:'red'})
    (jeansColor)-[:SIZE]->(:Size:Attribute{type:'small'})-[:QUANTITY]->(:Stock{quantity:2})
    (jeansColor)-[:SIZE]->(:Size:Attribute{type:'large'})-[:QUANTITY]->(:Stock{quantity:4})
    

    在此模型中,层次结构中的每个连续节点只有一个父节点。类型为 'red' 的 :Color 节点仅适用于 'jeans' 的 :Clothing 节点,对于不同类型的服装,在不同层次结构中还有其他 :Color 节点用于 'red'。同样,:Size 节点仅在其层次结构中有意义,因此上面的“小”和“大”尺寸仅适用于红色牛仔裤,并且 :Stock 节点也将特定于层次结构。我们在 :Color 和 :Size 节点上使用了第二个标签 :Attribute ,因此我们可以根据需要更通用地处理这些节点。

    每个级别的库存查询将使用可变长度关系,直到 :Item 节点并像这样对数量求和:

    MATCH (:Clothing{type:'jeans'})-[*]->(item:Item)
    RETURN sum(item.quantity) as stock
    

    类型查询将在另一个方向起作用(请注意,如果需要,我们可以在此处使用 :Attribute 标签而不是 :Color):

    MATCH (:Color{type:'red'})<-[*]-(clothing:Clothing)
    RETURN collect(distinct clothing.type) as clothing
    

    该模型需要相当严格的树,并且有许多重复的节点(因为具有相同属性的节点需要在树的不同分支上复制)。

    要考虑的替代模型是属性节点(:服装、颜色、:尺寸等)与相关项目直接相关的模型,因此每个项目都连接到适用于它的所有属性,类似于Gabor 的回答中的第 1 点。

    在这个模型中,每个属性节点只有一个,因此您不必处理节点重复,但是随着数据库中的项目数量越来越多,匹配中完成的工作可能会变得更加复杂,因为您将在与您正在搜索的属性相连的所有项目的交叉点处寻找项目节点(因此,要找到红色小牛仔裤,您将扩展到来自每个小、红色和牛仔裤属性节点的所有项目并且只保留三者之间共有的那些)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-04
      • 1970-01-01
      相关资源
      最近更新 更多