Mongodb:数据版本与search

涉及在MongoDB中实现数据版本化的方法以及在mongodb上版本化时间序列的文档结构

当我还需要能够处理查询时,我应该采用哪种数据结构进行版本控制?

假设我有8500个表格文件

{ _id: '12345-11', noFTEs: 5 } 

每个月我都会得到大约30个文档的noFTEs变更的详细信息,我希望将新的数据和前一个一起存储,并附上一个date。

这似乎导致:

 { _id: '12345-11', noFTEs: { '2015-10-28T00:00:00+01:00': 5, '2015-1-8T00:00:00+01:00': 3 } } 

但是我也希望能够search最新的数据(例如noFTEs > 4 ,元素应该被认为是5,而不是3)。 在那个阶段,我所知道的是我想使用最新的数据,而不会知道关键。 所以一个替代scheme将是一个数组

 { _id: '12345-11', noFTEs: [ {date: '2015-10-28T00:00:00+01:00', val: 5}, {date: '2015-1-8T00:00:00+01:00', val: 3} } } 

另一个select – 就像@thomasbormans在下面的评论中所build议的那样

 { _id: '12345-11', versions: [ {noFTEs: 5, lastModified: '2015-10-28T00:00:00+01:00', other data...}, {noFTEs: 3, lastModified: '2015-1-8T00:00:00+01:00', other...} } } 

我非常感谢在跳跃之前需要考虑的一些洞察,我担心会导致Mongo的工作量非常大。 (实际上还有其他3个领域可以结合起来进行search,其中一个领域也可能会随着时间的推移而发生变化。)

要在不影响最新数据的可用性和访问速度的情况下添加版本,请考虑创build两个集合:一个采用最新的文档,另一个在发生更改时将旧版本的文档存档。

您可以使用currentVersionCollection.findAndModify来更新文档,同时还可以在一个命令中接收前一个(或新的,取决于参数的)所述文档的版本。 然后,您只需要删除返回文档的_id ,添加时间戳和/或修订版号(当您没有这些时),并将其插入到归档集合中。

通过将每个旧版本存储在自己的文档中,您还可以避免文档增长,并防止文档在发生很大变化时冲破16MB文档限制。

当你build立一个noSQL数据库的模型时,你需要记住一些事情。

首先是每个文件的大小。 如果您在文档中使用数组,请确保它不会超过每个文档的16 Mb大小限制。

第二件事,你必须build模你的数据库,以便轻松地检索事物。 一些“非规范化”是可以接受的,以便于您的应用程序的速度和易用性。

所以,如果您需要了解当前的noFTE值,并且您只需要保留一个历史logging以便审计,则可以使用两个集合:

 collection["current"] = [ { _id: '12345-11', noFTEs: 5, lastModified: '2015-10-28T00:00:00+01:00' } ] collection["history"] = [ { _id: ...an object id... source_id: '12345-11', noFTEs: 5, lastModified: '2015-10-28T00:00:00+01:00' }, { _id: ...an object id... source_id: '12345-11', noFTEs: 3, lastModified: '2015-1-8T00:00:00+01:00' } ] 

通过这种方式,您可以保持最常访问的logging更小(我认为当前版本更频繁访问)。 这将使mongo更容易将“当前”集合保存在内存caching中。 并且文件将从磁盘中更快地被检索,因为它们更小。

我认为这个devise在内存优化方面是最好的。 但是,这个决定直接关系到你将使用什么样的数据。

编辑:我改变了我原来的回应,为每个历史logging创build分离的插入。 在我的原始答案中,我试图保持您的历史logging接近您的原始解决scheme,以关注非规范化主题。 但是,将历史保存在一个arrays中是一个糟糕的devise决定,我决定让这个答案更加完整。

在历史logging中保留分隔插入而不是创build数组的select很多:

1)每当你改变一个文档的大小(例如,插入更多的数据),mongo可能需要将这个文档移动到磁盘的空白部分,以容纳更大的文档。 这样,您最终创build存储空间,使您的collections更大。

2)当你插入一个新的文档时,Mongo会根据以前的插入/更新尝试预测它能变得多大。 这样,如果您的历史文档的大小相似,则填充因子将变为最佳。 然而,当你维持增长的arrays,这个预测不会很好,mongo会浪费空间和填充。

3)将来,如果它的规模过大,你可能会想缩小你的历史collections。 通常情况下,我们定义一个保留历史logging的策略(例如:5年),您可以备份和修剪比这更早的数据。 如果您为每个历史logging保留了分开的文档,那么执行此操作将更容易。

我可以find其他的原因,但是我相信这三点足以说明问题。