【发布时间】:2011-02-06 02:12:39
【问题描述】:
我有一个集合 t1,其架构中有以下字段
_id, field1, field1
我想设置field2的值field1,比如sql:
update t1 set field1=field2;
我如何在 MongoDB 中做到这一点?
【问题讨论】:
标签: mongodb mongodb-query
我有一个集合 t1,其架构中有以下字段
_id, field1, field1
我想设置field2的值field1,比如sql:
update t1 set field1=field2;
我如何在 MongoDB 中做到这一点?
【问题讨论】:
标签: mongodb mongodb-query
这里有好消息和坏消息。
坏消息是 AFAIK 你不能用一个 update() 调用来做到这一点 - mongo 不支持在更新中引用当前对象。
好消息是还有其他方法可以做到这一点,例如你可以运行一个 forEach 循环:
db.item.find(conditions...).snapshot().forEach( function (doc) {
doc.field1 = doc.field2;
db.item.save(doc);
});
您可以在管理 shell('mongo' 命令)中运行 forEach,或者通过特定驱动程序的某些方法(例如,在 PHP 中,我希望它可以与 mongodb.execute() 一起使用,如下所述: http://www.php.net/manual/en/mongodb.execute.php)
【讨论】:
从 3.4 版本开始,我们可以使用$addFields 聚合管道操作符,无需客户端处理,这是最有效的方式。
db.collection.aggregate(
[
{ "$addFields": { "field2": "$field1" }},
{ "$out": "collection" }
]
)
在 3.4 版之前,我们需要迭代 Cursor 对象并使用 $set 运算符添加具有现有“field1”值的新字段。您需要使用“批量”操作来执行此操作以获得最大效率。
MongoDB 3.2 弃用了 Bulk() 及其 associated methods,,因此从 3.2 开始,您需要使用 bulkWrite 方法。
var requests = [];
db.collection.find({}, { 'field1': 1 } ).snapshot().forEach(document => {
requests.push( {
'updateOne': {
'filter': { '_id': document._id },
'update': { '$set': { 'field2': document.field1 } }
}
});
if (requests.length === 1000) {
//Execute per 1000 operations and re-init
db.collection.bulkWrite(requests);
requests = [];
}
});
if(requests.length > 0) {
db.collection.bulkWrite(requests);
}
从版本 2.6 到 3.0,您可以使用 Bulk API。
var bulk = db.collection.initializeUnorderedBulOp();
var count = 0;
db.collection.find({}, { 'field1': 1 }).snapshot().forEach(function(document) {
bulk.find({ '_id': document._id }).updateOne( {
'$set': { 'field2': document.field1 }
});
count++;
if(count%1000 === 0) {
// Excecute per 1000 operations and re-init
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
})
// clean up queues
if(count > 0) {
bulk.execute();
}
【讨论】:
aggregate 和 out 不合适,如果需要 match:最终集合将仅包含匹配的文档。
这可以通过:
db.nameOfCollection.find().forEach(
function (elem) {
db.nameOfCollection.update(
{
_id: elem._id
},
{
$set: {
field2: elem.field1
}
}
);
}
);
【讨论】: