【问题标题】:How would you model a table to record changes in other tables' records' values?您将如何对表建模以记录其他表记录值的更改?
【发布时间】:2012-11-01 11:32:12
【问题描述】:

我正在编写一个模型来记录对其他模型所做的更改,以便记录每个属性更改。我正在寻找有关如何最好地构建更改记录表的意见。

例如,我有一个带有name 属性的User 模型。当该用户的名称从Bob 更改为Ted 时,我想将Change 记录保存到数据库中。

此外,如果用户同时更新User 上的多个属性,我想将这些属性记录为单个Change。例如,Usernameemail 属性分别从Bobbob@bobsdomain.com 更改为Tedted@teddy.com

给定对象上正在更改的属性集是任意的。您将如何构建表格?

目前,我正在做类似以下的事情(简化):

Changes:
  user_id:integer
  changed_fields:string
  old_values:text
  new_values:text

在上述示例中,这些记录如下所示:

:changed_fields => "name", 
:old_values => "Bob", 
:new_values => "Ted"

:changed_fields => "name,email", 
:old_values => "Bob,bob@bobsdomain.com", 
:new_values => "Ted,ted@teddy.com"

Change 模型上,我有特殊的 getter/setter 方法,可以解析输入/输出以映射到特定格式。

有没有更好的方法来模拟这种东西?

如果不是,考虑到值可以是任意的,那么格式化数据库值以使解析输入/输出工作的最佳方式是什么。

我使用 Postgres 作为我的数据库,使用 ActiveRecord 作为 ORM。

【问题讨论】:

    标签: database postgresql database-design activerecord schema


    【解决方案1】:

    同时存储旧值和新值是多余的。您可以改为在更改时仅存储新值,并确保在创建新行时也添加更改记录。如果一行被修改了 N 次,那么它在修改表中会有 N+1 条记录,如果需要可以追溯查找它们之间的差异。

    事实上,一种方法是只有一张表包含所有版本的数据。通过插入新行来进行编辑,而不是就地更新任何行。我在使用布尔“最新”字段或使用另一个表中的外键来引用每一行的当前版本时采用了这种方法。

    虽然这些天我正在使用 django-reversion 包为我实现修订跟踪。它使用单个表来记录所有跟踪表的所有版本,存储每个版本的每个对象状态的 JSON 表示。它使用一个额外的表来跟踪整个变更集,因此它可以对跨越多个对象的变更进行版本化。

    最适合您的解决方案将取决于您需要能够在您的表上高效地执行哪些操作,以及您的 ORM 使您可以轻松使用哪些操作。我希望这个答案有助于指出一些在其他环境中有效的方法。

    【讨论】:

    • 谢谢杰米。这实际上非常有用。我没有想到旧值是多余的。我想我可能会采用这种方法,因为它不需要我修改 AR 期望找到模型的方式。
    猜你喜欢
    • 2018-04-22
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多