Neo4j数据建模:私有节点,丰富的关系,锁定

时间:2016-10-31 07:47:38

标签: performance neo4j scalability data-modeling spring-data-neo4j-4

使用的版本:用于POJO映射的Spring-data-neo4j 4.2.0.M1的Neo4j 3.0.6

我正在尝试选择如何使用neo4j对数据建模,并比较不同解决方案的优缺点。

要求:

  • 电影有一个动态的元数据列表(元数据有3个属性:'key','value','locale')。预先不知道电影的元数据的数量,也不是可能的键。它们必须与其他Movie技术属性分离,因为它们已本地化并被视为业务数据。
  • 元素由电影拥有,并且始终可以从电影中访问。它们无法与其他电影共享
  • 必须可以对元数据值进行快速提取查询

电影元数据示例:

Movie metadata
  locale 'en_GB':
    title: 'Jurassic Park'
    description: 'description in english'
  locale 'fr_FR':
    description: 'description en francais'
  locale 'none':
    actor: 'Jeff Goldblum'

enter image description here 解决方案A

  • 每个元数据一个节点(每个节点有3个属性:'key','value','locale')
  • 缺点:私有概念将被实施(由于spring-data-neo4j / neo4j-ogm不支持,删除要手动管理的元数据孤立节点)

解决方案B

  • 每个区域设置一个唯一节点(包含1个属性:'locale')(例如:'en_GB')
  • 元数据为丰富关系(包含2个关系属性:'key','value')
  • 缺点:要创建关系,必须在区域设置节点上执行锁定

有人对解决方案B有经验吗? 需要锁定将由数百万个其他节点共享的节点有多糟糕? 什么是对性能和可扩展性的影响?

是否有人拥有更好的建模解决方案?

2 个答案:

答案 0 :(得分:3)

tl,dr:采用方法A.除了定期清理之外,不要打扰孤立的:Locale节点,它们对查询性能没有影响。

你的方法'A'是迄今为止更好的解决方案。您确实需要从:Movie节点移出该数据,这是正确的,因为它必须是嵌套的Map或Map列表,Node属性都不支持这两种。对于存储,您可以将这些转换为列表映射,但查询非常困难,更不用说快速查询。您对“孤立”节点的关注是无关紧要的;它会严重影响查询性能和数据大小(如果有的话),并且非常容易定期清理,以便在任何情况下放松一下。

MATCH (x:Locale) WHERE NOT (x) <- [:METADATA] - () DETACH DELETE x

每月做一次,或者从不做,这对你影响不大。您的查询已经受到路径其余部分的限制,因此除非孤立的:Locale节点数量大大超过附加的节点,否则您只需将一小部分添加到查询中最大的集合中,也将在第一次通过时通过查询操作删除。

至于锁定,它只会影响写入查询,并且只有在写入事务处于打开状态时才会影响。在写入过程中,您可以运行一百万个只读查询,并且不会有任何影响。尽管如此,第二个模型容易受到查询性能降低的影响,因为如上所述,您无法在关系属性上放置索引。

答案 1 :(得分:1)

您可以直接将 存储为每个Movie节点的属性(无需借助keyvalue)。这是最简单的方法,可以避免锁定问题,并最大限度地减少所需的节点和关系数量。您可以随时向节点自由添加更多属性。此方法还允许您为开始查询时需要快速访问的特定Movie属性添加索引。

例如:

CREATE (m:Movie {id: 123, title: 'Men in black', director: 'Barry Sonnenfeld'});

[UPDATE]

如果您需要将“元数据”与“数据”完全分开,并且还需要能够本地化元数据(包括locale属性的规范),那么您可以关联每个{ {1}}节点,每个语言环境都有一个Movie节点。 Metadata节点将直接包含特定Metadata节点的单个区域设置的所有元数据属性。

Cypher可用于执行“级联删除”。例如:

Movie