0

我有一个集合 A,其中包含以下形式的文档:

{
  _id: 12345,
  title: "title"
}

和文件 B 的形式:

{
  _id: 12345,
  newAttribute: "newAttribute12345"
}

我想更新集合 A 以获得以下文件:

{
  _id: 12345,
  title: "title"
  newAttribute: "newAttribute12345"
}

这时我用

update({_id: doc._id}, {$set: {newAttribute: doc.newAttrubute}})

,但我需要为我的所有文档循环运行 10,000 次。如何在 1 db 调用中或以最有效的方式更新多个文档(通过 _id)?(这基本上是一个加入/批量更新属性操作)

我使用 mongodb 2.6

4

3 回答 3

2

考虑以下场景,两个集合名称为titleattribute

title集合包含以下文件:

[{
_id: 12345,
title: "title"
},
{
_id: 12346,
title: "title1"
}]

并且attribute集合包含以下文档:

[{
_id: 12345,
newAttribute: "newAttribute12345"
},
{
_id: 12346,
newAttribute: "newAttribute12346"
},
{
_id: 12347,
newAttribute: "newAttribute12347"
}]

并且您想更新title集合,因为使用此标准title._id = attribute._id使用带有以下脚本的mongo 批量更新:

var bulk = db.title.initializeOrderedBulkOp(); 
var counter = 0;
db.attribute.find().forEach(function(data) {
    var updoc = {
      "$set": {}
    };
    var updateKey = "newAttribute";
    updoc["$set"][updateKey] = data.newAttribute;
    bulk.find({
      "_id": data._id
    }).update(updoc);
    counter++;
    // Drain and re-initialize every 1000 update statements
    if(counter % 1000 == 0) {
      bulk.execute();
      bulk = db.title.initializeOrderedBulkOp();
    }
  })
  // Add the rest in the queue
if(counter % 1000 != 0) bulk.execute();
于 2015-06-03T11:56:01.367 回答
0

一个可能/有问题的答案是在mongo中加入hacky(也许有更好的东西): http ://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/

这样做的问题是我必须稍后交换集合,这需要我知道我的集合的属性

var r = function(key, values){
    var result = { prop1: null, prop2: null };
    values.forEach(function(value){
       if (result.prop1 === null && value.prop1 !== null) {
           result.prop1 = value.prop1;
       }
       if (result.prop2 === null && value.prop2 !== null) {
           result.prop2 = value.prop2;
       }
    })
    return result;
};

var m = function(){
    emit(this._id, { prop1: this.prop1, prop2: this.prop2 })
}

db.A.mapReduce(m1, r, { out: { reduce: 'C' }});
db.B.mapReduce(m1, r, { out: { reduce: 'C' }});
于 2015-06-03T11:51:56.973 回答
0

您可以使用该cursor.forEach方法

db.collectionA.find().forEach(function(docA){ 
    db.collectionB.find().forEach(function(docB){
        if(docA._id === docB._id){ 
            docA.newAttribute = docB.newAttribute;     
            db.collectionA.save(docA);
        }
    })
})

> db.collectionA.find()
{ "_id" : 12345, "title" : "title", "newAttribute" : "newAttribute12345" }
于 2015-06-03T11:55:40.543 回答