我有一个集合t1
,其架构中包含以下字段
_id, field1, field1
我希望set field2
的值field1
类似于sql:
update t1 set field1=field2;
我如何在MongoDB中执行此操作?
这里有好消息和坏消息.
坏消息是AFAIK你不能通过单个update()调用来做 - mongo不支持在更新中引用当前对象.
好消息是还有其他方法可以做到,例如你可以运行forEach循环:
db.item.find(conditions...).forEach( function (doc) { doc.field1 = doc.field2; db.item.save(doc); });
您可以在admin 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()
及其相关方法,因此从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(); }