维护mongodb集合的秩序

维护mongodb集合的秩序,mongodb,mongoid,Mongodb,Mongoid,我有一个收藏,里面有很多文档(可能有数百万)。当用户插入新文档时,我希望有一个字段来维护我可以索引的数据的“顺序”。例如,如果一个字段是时间,在这种格式“1352392957.46516”中,如果我有三个文档,第一个带时间:1352392957.46516,第二个带时间:1352392957.48516(20ms后),第三个带1352392957.49516(10ms后),我希望有另一个字段,其中第一个文档为0,第二个为1,第三个2,依此类推 我希望这样做的原因是,我可以索引该字段,然后当我进行

我有一个收藏,里面有很多文档(可能有数百万)。当用户插入新文档时,我希望有一个字段来维护我可以索引的数据的“顺序”。例如,如果一个字段是时间,在这种格式“1352392957.46516”中,如果我有三个文档,第一个带时间:1352392957.46516,第二个带时间:1352392957.48516(20ms后),第三个带1352392957.49516(10ms后),我希望有另一个字段,其中第一个文档为0,第二个为1,第三个2,依此类推

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

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

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

有没有一种方法可以自动做到这一点?还是我必须实施这个?或者有没有一种更有效的方法来完成我所描述的工作?

如果您要为一次插入更新数百万个文档,那么这远远超出了“较慢插入”的范围-这种方法使您的整个集合成为活动工作集。类似地,为了与键值进行
$mod
比较,您必须比较索引中的每个键值

鉴于您对排序采样顺序的要求,我不确定您是否可以采取更有效的方法

我会用它随机取一份文件。
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);
//在时间字段上添加索引
db.data.ensureIndex({'time':1})
//清点文件数量
var dc=db.data.count()
//每1000个文档迭代并采样一次
var i=0;var sampleSize=1000;var结果=[];
而(i
如果您要为一次插入更新数百万个文档,这远远超出了“较慢插入”的范围-这种方法使您的整个集合成为活动工作集。类似地,为了与键值进行
$mod
比较,您必须比较索引中的每个键值

鉴于您对排序采样顺序的要求,我不确定您是否可以采取更有效的方法

我会用它随机取一份文件。
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);
//在时间字段上添加索引
db.data.ensureIndex({'time':1})
//清点文件数量
var dc=db.data.count()
//每1000个文档迭代并采样一次
var i=0;var sampleSize=1000;var结果=[];
而(i
这应该可以很好地回答您的问题。为什么需要“插入”文档?更新“所有后续整数”听起来很痛苦。有什么原因不能添加到结尾吗?整数也应该是排序顺序吗?整数应该是排序顺序,因为这是我能想到的有效向下采样数据的唯一方法。我希望用户能够插入时间戳可能早于结束时间的旧数据。此外,我同意这听起来很痛苦,但对于我的应用程序,我希望插入速度较慢,查询速度较快。但是,如果有更好的方法来实现我所说的,那也太好了。或者说,有没有一种方法可以访问排序后的索引并对其执行$mod?比如,如果我保持数据未排序,并执行类似的操作,db.data.find().sort({time:1}),但然后使用返回结果的顺序对该结果进行修改?这不起作用,但类似于以下内容:db.data.find().sort({time:1}).find({index:{$mod:[1000,0]})这应该可以很好地回答您的问题。为什么需要“插入”文档?更新“所有后续整数”听起来很痛苦。有什么原因不能添加到结尾吗?整数也应该是排序顺序吗?整数应该是排序顺序,因为这是我能想到的有效向下采样数据的唯一方法。我希望用户能够插入时间戳可能早于结束时间的旧数据。此外,我同意这听起来很痛苦,但对于我的应用程序,我希望插入速度较慢,查询速度较快。但是,如果有更好的方法来实现我所说的,那也太好了。或者说,有没有一种方法可以访问排序后的索引并对其执行$mod?比如,如果我保持数据未排序,并执行类似的操作,db.data.find().sort({time:1}),但然后使用返回结果的顺序对该结果进行修改?这不起作用,但是类似这样的东西:db.data.find().sort({time:1}).find({index:{$mod:[1000,0]})我想这可能对我有用,反正我计划缓存查询结果。我只需要在添加了1000个条目(在本例中)后重新运行这种类型的查询,最后我使用了map reduce。上面的答案证明太慢了。现在我要做的是使用mapReduce的scope选项,并保留一个外部计数和索引。我使用sort对输入进行排序,并构建一个带有on数组的结果文档