如何批量向MongoDB中的每条记录添加随机字段

时间:2015-11-18 16:24:33

标签: mongodb

关于随机排序结果或随机获取单个记录,有许多问题和答案。答案建议添加一个随机字段,在该字段上创建索引,然后进行随机抽取。它看起来像:

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文件,我需要经常导入它,因此不能等待多个小时才能更新它。

2 个答案:

答案 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");
        });
    }
});

如果修改缓冲区大小/增量参数,它可能会更快。

当然,假设您可以轻松重新导入数据。