您如何建模表以记录其他表的记录值的变化?

时间:2012-11-13 00:33:40

标签: database postgresql database-design activerecord schema

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

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

此外,如果用户同时更新User上的多个属性,我希望将这些属性记录为单个Change。例如,User分别将nameemail属性从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作为我的DB,使用ActiveRecord作为ORM。

1 个答案:

答案 0 :(得分:0)

存储旧值和新值都是多余的。您可以在更改时仅存储新值,并确保在创建新行时也添加更改记录。如果一行已更改N次,则更改表中将包含N + 1条记录,如果需要,您可以追溯查找它们之间的差异。

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

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

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