1

我有一个包含许多文档(可能数百万)的集合。当用户插入一个新文档时,我希望有一个字段来维护我可以索引的数据的“顺序”。例如,如果一个字段是时间,格式为“1352392957.46516”,如果我有三个文档,第一个是时间:1352392957.46516,第二个是时间:1352392957.48516(20 毫秒后),第三个是 1352392957.49516(10 毫秒后)喜欢有另一个字段,其中第一个文档为 0,第二个为 1,第三个为 2,依此类推。

我想要这个的原因是我可以索引该字段,然后当我进行查找时,我可以执行有效的 $mod 操作来对数据进行下采样。因此,例如,如果我有一百万个文档,并且我只希望其中 1000 个均匀分布,我可以在整数字段上执行 $mod [1000, 0] 。

我不能在时间字段上这样做的原因是因为它们可能没有完美间隔,或者可能都是偶数或奇数,因此 mod 无法工作。因此,单独的整数字段将以线性增加的方式保持顺序。

此外,您应该能够在集合中的任何位置插入文档,因此所有后续字段都需要更新。

有没有办法自动做到这一点?还是我必须实施这个?或者有没有更有效的方法来做我所描述的事情?

4

1 回答 1

1

It is well beyond "slower inserts" if you are updating several million documents for a single insert - this approach makes your entire collection the active working set. Similarly, in order to do the $mod comparison with a key value, you will have to compare every key value in the index.

Given your requirement for a sorted sampling order, I'm not sure there is a more efficient preaggregation approach you can take.

I would use skip() and limit() to fetch a random document. The skip() command will be scanning from the beginning of the index to skip over unwanted documents each time, but if you have enough RAM to keep the index in memory the performance should be acceptable:

// 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);
于 2012-11-08T20:13:56.307 回答