我有一个会有很多文件的集合(可能是数百万)。当用户插入新文档时,我希望有一个字段来维护我可以索引的数据的“顺序”。例如,如果一个字段是时间,以这种格式“1352392957.46516”,如果我有三个文件,第一个带时间:1352392957.46516,第二个带时间:1352392957.48516(20ms后),第三个带1352392957.49516(10ms后)我会喜欢有另一个字段,其中第一个文档将为0,第二个将为1,第三个为2,依此类推。
我想要这个的原因是我可以索引该字段,然后当我进行查找时,我可以执行有效的$ mod操作来对数据进行下采样。因此,例如,如果我有一百万个文档,并且我只想要1000个均匀间隔,我可以在整数字段上执行$ mod [1000,0]。
我在时间字段上无法做到这一点的原因是因为它们可能没有完美的间隔,或者可能都是偶数或奇数,因此mod不起作用。因此,单独的整数字段将使顺序保持线性增长。
此外,您应该能够在集合中的任何位置插入文档,因此需要更新所有后续字段。
有没有办法自动执行此操作?或者我必须实现这个?或者是否有更有效的方式来完成我所描述的内容?
答案 0 :(得分:1)
如果要为单个插入更新数百万个文档,它远远超出“慢速插入” - 这种方法使整个集合成为活动工作集。同样,为了与键值进行$mod
比较,您必须比较索引中的每个键值。
鉴于您需要排序的抽样订单,我不确定您可以采用更有效的preaggregation方法。
我会使用skip()
and limit()
来获取随机文档。 skip()
命令将从索引的开头进行扫描,以便每次都跳过不需要的文档,但是如果你有足够的RAM来保存索引在内存中,那么性能应该是可以接受的:
// Add an index on time field
db.data.ensureIndex({'time':1})
// Count number of documents
var dc = db.data.count()
// Iterate and sample every 1000 docs
var i = 0; var sampleSize = 1000; var results = [];
while (i < dc) {
results.push(db.data.find().sort({time:1}).skip(i).limit(1)[0]);
i += sampleSize;
}
// Result array of sampled docs
printjson(results);