MongoDB的/ NoSQL的:保持文档更改历史记录MongoDB的/ NoSQL的:保持文档更改

2019-05-12 19:03发布

在数据库应用中一个相当普遍的要求是跟踪在数据库中更改一个或多个特定的实体。 我听说过这个叫行版本,日志表或历史表(我敢肯定有其他的名字为它)。 有许多的方式来处理它在RDBMS - 你可以写所有源表到一个表(更多的日志)的所有更改或有一个单独的历史表中的每个源表。 您还可以在应用程序代码或通过数据库触发器要么管理日志记录的选项。

我试图想通过什么相同的问题的解决方案看起来像一个NoSQL的/数据库文件(特别是MongoDB的),以及它如何可以以统一的方式来解决。 难道是为文档中创建版本号,从来没有覆盖他们一样简单? 创建“真实”与“登录”文件单独集合? 这将如何影响查询和性能?

无论如何,这是与NoSQL数据库一个常见的情况,如果是这样,有一个共同的解决方案?

Answer 1:

好问题,我一直在寻找到这一点我自己也是如此。

每个变化都创建新版本

我遇到了版本控制模块的Mongoid驱动程序的Ruby。 我没有用它自己,但我能找到的 ,它增加了一个版本号到每个文档。 旧版本嵌入文档本身英寸 主要的缺点是整个文档的每个变化 ,这将导致大量的重复的内容,当你处理大文件存储复制 。 这种方法很好,虽然当你处理小型文件和/或不经常更新的文件。

只有专卖店变化的新版本

另一种方法是只存储在一个新的版本改变的领域 。 然后,你可以“扁平化”的历史重建文件的任何版本。 这是相当复杂的,虽然,因为你需要追踪你的模型和存储的更新变化,并在您的应用程序可以重建了最新文件的方式删除。 这可能是棘手的,因为你要处理的结构化文档,而不是平的SQL表。

在文档内保存修改

每场也能有一个独立的历史。 重建文件给定的版本更容易这样。 在您的应用程序没有明确地跟踪变化,只是创建属性的新版本,当你改变它的价值。 文档可以是这个样子:

{
  _id: "4c6b9456f61f000000007ba6"
  title: [
    { version: 1, value: "Hello world" },
    { version: 6, value: "Foo" }
  ],
  body: [
    { version: 1, value: "Is this thing on?" },
    { version: 2, value: "What should I write?" },
    { version: 6, value: "This is the new body" }
  ],
  tags: [
    { version: 1, value: [ "test", "trivial" ] },
    { version: 6, value: [ "foo", "test" ] }
  ],
  comments: [
    {
      author: "joe", // Unversioned field
      body: [
        { version: 3, value: "Something cool" }
      ]
    },
    {
      author: "xxx",
      body: [
        { version: 4, value: "Spam" },
        { version: 5, deleted: true }
      ]
    },
    {
      author: "jim",
      body: [
        { version: 7, value: "Not bad" },
        { version: 8, value: "Not bad at all" }
      ]
    }
  ]
}

标记文档的一部分,在一个版本中删除还是有点尴尬,但。 你可以引入一个state字段从您的应用程序恢复,可以被删除的部分/:

{
  author: "xxx",
  body: [
    { version: 4, value: "Spam" }
  ],
  state: [
    { version: 4, deleted: false },
    { version: 5, deleted: true }
  ]
}

有了这些方法,你可以在一个单独的收集存储在一个采集和历史数据的先进的日期和扁平的版本。 这应该提高查询的时候,如果你只是在一个文件的最新版本感兴趣。 但是,当你既需要最新版本的数据和历史数据,您需要执行两个查询,而不是一个。 因此,使用一个单一的集合与两个单独集合的选择应取决于你的应用程序如何往往需要历史版本

大多数这样的回答的只是我的想法倾吐心事,我还没有真正尝试任何的这个呢。 回想起来,第一个选项可能是最简单,最好的解决办法,除非重复数据的开销是为您的应用程序非常显著。 第二个选项是相当复杂的,可能是不值得的。 第三个选项是基本的选择两者的优化,应该更容易实现,但可能是不值得的实施工作,除非你真的无法选择一个去。

期待这一反馈,以及其他人的解决问题的方法:)



Answer 2:

我们已经部分地在我们网站上实现这一点,我们使用的“存储修订在一个单独的文件”(和单独的数据库)。我们写了一个自定义函数返回的比较和我们存储。不是很难,可以允许自动恢复。



Answer 3:

为什么不能在文档中保存修改的变化?

而不是存储版本对每个密钥对的,该文件在当前的密钥对始终代表存储在历史阵列内最近的状态和变化的“日志”。 只有那些创建以来已经改变了密钥将在日志中的条目。

{
  _id: "4c6b9456f61f000000007ba6"
  title: "Bar",
  body: "Is this thing on?",
  tags: [ "test", "trivial" ],
  comments: [
    { key: 1, author: "joe", body: "Something cool" },
    { key: 2, author: "xxx", body: "Spam", deleted: true },
    { key: 3, author: "jim", body: "Not bad at all" }
  ],
  history: [
    { 
      who: "joe",
      when: 20160101,
      what: { title: "Foo", body: "What should I write?" }
    },
    { 
      who: "jim",
      when: 20160105,
      what: { tags: ["test", "test2"], comments: { key: 3, body: "Not baaad at all" }
    }
  ]
}


Answer 4:

人们可以有一个当前的NoSQL数据库和历史数据库的NoSQL。 将会有一夜间ETL每天跑。 这ETL将记录与时间戳每个值,所以不是值,它会永远是元组(版本字段)。 如果有对当前值进行了更改,在这个过程中节省空间这将只记录一个新值。 例如,这种历史的NoSQL数据库JSON文件可以看起来像这样:

{
  _id: "4c6b9456f61f000000007ba6"
  title: [
    { date: 20160101, value: "Hello world" },
    { date: 20160202, value: "Foo" }
  ],
  body: [
    { date: 20160101, value: "Is this thing on?" },
    { date: 20160102, value: "What should I write?" },
    { date: 20160202, value: "This is the new body" }
  ],
  tags: [
    { date: 20160101, value: [ "test", "trivial" ] },
    { date: 20160102, value: [ "foo", "test" ] }
  ],
  comments: [
    {
      author: "joe", // Unversioned field
      body: [
        { date: 20160301, value: "Something cool" }
      ]
    },
    {
      author: "xxx",
      body: [
        { date: 20160101, value: "Spam" },
        { date: 20160102, deleted: true }
      ]
    },
    {
      author: "jim",
      body: [
        { date: 20160101, value: "Not bad" },
        { date: 20160102, value: "Not bad at all" }
      ]
    }
  ]
}


文章来源: MongoDB/NoSQL: Keeping Document Change History
标签: mongodb nosql