精华 Neo4j官方教程:第23节,版本控制
发布于 1 天前 作者 pangguoming 17 次浏览 来自 分享

教程目录 引自:https://neo4j.com/docs/getting-started/data-modeling/versioning/

版本控制

每次重构数据模型时,都会创建新的版本。跟踪数据结构的变化或显示当前和过去的值对于审计目的、趋势分析等非常有价值。本页面概述了可以用来跟踪随时间变化的数据的不同建模方式。


实体的版本控制

通过对相关实体进行版本控制,可以跟踪数据的变化。这种策略在以下情况下非常有用:

  • 访问图中特定实体(例如节点)的多个版本(例如产品在不同时间的名称)。
  • 仅检索最新版本(例如产品的当前名称)。

image

示例:图中显示实体的不同版本,其属性值随时间变化

  • 实体版本控制的特点:
    • 实体 Product 通过显式关系链接到其不同版本。
    • 实体 Product 是不可变的。只有存储在不同版本(State 节点)中的属性会发生变化。
    • LATEST 关系将实体 Product 链接到其最新版本(State),该版本也是版本 2(V2)。

优缺点

优点 缺点
建模、查询和维护简单。 更新节点需要删除 LATEST 关系,并创建实体与其最新版本之间的新关系。
对最终用户显式,无需任何转换。 如果不使用其他版本控制模式,可能会受到限制,因为如果不是最新版本,可能很难知道要检索哪个版本。

查询示例

以下是使用实体版本控制策略的常见查询示例:

获取 ID 为 ‘1’ 的产品版本 2 的名称

MATCH (:Product {id:1})-[:V2]->(s:State)
RETURN s.name

获取 ID 为 ‘1’ 的产品最新版本的名称

MATCH (:Product {id:1})-[:LATEST]->(s:State)
RETURN s.name

基于时间的实体版本控制

实体版本控制的一种变体是基于时间的方法。这在以下情况下非常有用:

  • 图快照:通过检索图中某个时间点的所有有效元素(节点和关系)(例如,2023 年 6 月 12 日星期一可用的产品)。
  • 图差异:比较两个不同时间戳的图快照(例如,哪些节点被添加、哪些被删除、哪些保持不变)。
  • 时间序列遍历:仅遍历图中某个时间点的有效元素(节点或关系),以找到连接基于时间事件的关系的时间顺序(例如,带有车站之间的行程关系的共享单车图)。
  • 图历史:建模数据变化的历史。 image

示例:基于时间的实体版本控制

  • 基于时间的版本控制特点:
    • 每个元素都有专门的 validFrom/validTo 时间属性。
    • 节点只有在其有效时间范围重叠时才能共享关系。
    • 信息可能会重复。
    • 图的完整历史可用。

优缺点

优点 缺点
每个元素都有明确的时间间隔,在该时间间隔内元素有效。 如果节点状态发生变化,节点必须被复制,并分配新的有效时间间隔。
状态绑定到特定元素(无需额外关系)。 更新节点需要创建连接到新节点/状态的新关系,并分配新的有效时间间隔。
可以聚合所有元素(或某个时间点的有效元素)。 数据重复无法避免。

查询示例

以下是使用基于时间的实体版本控制策略的常见查询示例:

获取产品 “Rice Cooker” 的当前价格

MATCH (p:Product)
WHERE p.name = "Rice Cooker" AND p.validTo = ∞
RETURN p.price

获取产品 “Rice Cooker” 在 11 月的价格

MATCH (p:Product)
WHERE p.name = "Rice Cooker"
AND datetime(p.validFrom) <= datetime("November") <= datetime(p.validTo)
RETURN p.price

获取当前产品目录及价格

MATCH ()-[r:HAS_PRODUCT]->(p)
WHERE r.validTo = ∞
RETURN p.name, p.price

链表

链表是一种建模策略,当对象的顺序很重要时非常有用。

链表的用途:

  • 事件顺序,例如获取银行账户执行的交易顺序。
  • 基于关系获取列表中的前一个和下一个元素(例如播放列表中的下一首歌曲,或撤销文本文档中的操作)。 image

示例:使用链表模型设计进行版本控制

  • 链表特点:
    • 实体 Product 链接到序列的第一个元素,也可以链接到最后一个元素。
    • 与实体版本控制一样,实体 Product 在此处也是不可变的。
    • 序列中的每个元素通过 NEXT 关系链接到下一个元素。

优缺点

优点 缺点
使用关系获取下一个/前一个元素效率高。 如果不使用其他版本控制模式,可能仅限于非常具体的用例。
建模和维护简单。 很难找到不是第一个或最后一个的特定版本。
对最终用户显式。 -

查询示例

以下是使用链表版本控制策略的常见查询示例:

获取产品 “Professional chair” 的下一个名称

MATCH (:State{name: "Professional chair"})-[:NEXT]->(s:State)
RETURN s.name

获取 ID 为 ‘1’ 的产品的前一个名称

MATCH (:Product {id:1})-[:LAST]->(:State)<-[:NEXT]-(s:State)
RETURN s.name

时间线树

如建模设计中所述,时间线树是一种常见的建模设计。当您想要跟踪变化时,它可以是一种有用的策略。在此示例中,时间线结构从年份扩展到天,其余的非时间数据节点是图中包含重要数据的节点。 image

示例:图中显示两个不同的时间线按年份划分

查询示例

如果您想找到某个时间段内发生的所有购买,例如 2012 年 12 月的所有购买,可以从 2012 年导航到 12 月,然后从该分支下的所有叶节点(没有后代的节点)中获取数据:

MATCH (root:Timeline)-[:IN_YEAR]->(year:Year {value:2012})-[:IN_MONTH]->(month:Month {value:12})
WITH month
MATCH (month)-[:ON_DAY]->(day)
MATCH (purchase:Purchase)-[:OCCURRED]->(day)
RETURN purchase

组合方法

一些复杂的用例需要结合上述一种或多种建模技术,因为每种技术都有其优点和缺点。

示例:结合时间线树的更复杂版本控制方法

  • 具体组合取决于用例。
  • 应考虑查询时间和事务频率等因素。
回到顶部