2015-11-18 58 views
1

关于随机排序结果或随机获取单个记录有许多问题和解答。答案建议添加一个随机字段,在该字段上创建索引,然后进行随机抽取。它看起来像:如何批量向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文件,我需要经常导入它,所以不能等待几个小时才能更新它。

+0

可能你只是稍微等待版本3.2,那么你可以使用'$ sample'操作符:https://docs.mongodb.org/manual/release-notes/3.2-reference/ – nickmilon

回答

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(); 
} 
0

如果集合仅仅是静态数据,并你从其他人那里获得一个BSON文件,通过一个过滤器将BSON文件串流生成一个新的BSON文件可能会更快,然后你可以使用mongoimport导入这个BSON文件。

下面是我用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"); 
     }); 
    } 
}); 

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

这当然假设您有重新导入数据的奢侈。

相关问题