关于随机排序结果或随机获取单个记录,有许多问题和答案。答案建议添加一个随机字段,在该字段上创建索引,然后进行随机抽取。它看起来像:
db.myindex.find().forEach(function(doc) {
db.myindex.update({_id: doc._id}, {$set: {rand: Math.random()}})
})
这很好用,但需要几个小时(很多很多数据)。它似乎受写锁定的限制,这是有意义的,因为每个记录都会发生更新。我如何批量执行此操作?我试过了:
var bulk = db.myindex.initializeUnorderedBulkOp();
bulk.find({}).update( { $set: { rand: Math.random() } } );
bulk.execute();
但是它将每个记录的rand字段设置为相同的值!我该如何解决?
编辑:顺便说一句,我需要这样做的原因是因为我从其他人那里获得了一个巨大的bson文件,我需要经常导入它,因此不能等待多个小时才能更新它。
答案 0 :(得分:1)
介绍一个循环,其中批量操作每1000个文档发送到服务器一次,或者在64MB BSON限制下可以进行多次修改:
var bulk = db.myindex.initializeOrderedBulkOp();
var counter = 0;
db.myindex.find().forEach(function(doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "rand": Math.random() }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute();
bulk = db.myindex.initializeOrderedBulkOp();
}
});
if (counter % 1000 != 0){
bulk.execute();
}
答案 1 :(得分:0)
如果集合只是静态数据,并且您从其他人那里获得了BSON文件,则通过过滤器流式传输BSON文件以生成新的BSON文件可能会更快,然后可以使用mongoimport导入该文件。 / p>
这是我使用nodeJS编写的一个可以大约1GB / min处理BSON文件的文件。
var bson = require('bson');
var BSON = new bson.BSONPure.BSON();
var BSONStream = require('bson-stream');
var fs = require('fs');
var sb = require('stream-buffers');
var rs = fs.createReadStream('tweets.bson');
var ws = fs.createWriteStream('tweets_random.bson',{flags:'a'});
var writeBuffer = new sb.WritableStreamBuffer({
initialSize: (1024*1024),
incrementAmount: (10*1024)
});
rs.pipe(new BSONStream()).on('data',function(obj) {
obj.rand = Math.random();
writeBuffer.write(BSON.serialize(obj));
if(writeBuffer.size()>(1024*1024)) {
var size = writeBuffer.size();
ws.write(writeBuffer.getContents(),function() {
console.log("Wrote",size,"bytes");
console.log("Buffer has:",writeBuffer.size(),"bytes left");
});
}
});
如果修改缓冲区大小/增量参数,它可能会更快。
当然,假设您可以轻松重新导入数据。