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

Neo4j data modeling: private owned nodes, rich relationships, locks

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

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

要求:

电影元数据示例:

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

解决方案 A

解决方案 B

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

有人有更好的建模解决方案吗?

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

例如:

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

[更新]

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

Cypher 可用于执行 "cascading deletes"。例如:

MATCH (m:Movie {id: 123})
OPTIONAL MATCH p=(m)-->()
DELETE p;

tl,dr:采用方法 A。不要理会孤立的 :Locale 节点,除了定期清理,它们不会影响查询性能。

您的方法 'A' 是迄今为止更好的解决方案。您确实需要将该数据移出 :Movie 节点,您是对的,因为它必须是嵌套地图或地图列表,节点属性都不支持这两种情况。对于存储,您可以将它们转换为列表的 Map,但这将很难查询,更不用说快速查询了。您对 "orphaned" 个节点的关注是微不足道的;它会对查询性能和数据大小产生微不足道的影响,并且在任何情况下都非常容易定期清理以使您放心。

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

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

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