MongoDB 多个更新属性
MongoDB multiple update attributes
我有一个集合 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)? (这基本上是一个 join/bulk 更新属性操作)
我用mongodb2.6
一个 possible/problematic 的答案是 hacky 加入 mongo (也许有更好的东西):
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' }});
你可以使用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" }
考虑以下场景,两个集合名称为 title
和 attribute
。
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 bulk 使用以下脚本进行更新:
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();
我有一个集合 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)? (这基本上是一个 join/bulk 更新属性操作)
我用mongodb2.6
一个 possible/problematic 的答案是 hacky 加入 mongo (也许有更好的东西): 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' }});
你可以使用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" }
考虑以下场景,两个集合名称为 title
和 attribute
。
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 bulk 使用以下脚本进行更新:
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();