首页 文章

使用文档中的另一个字段值更新字段[重复]

提问于
浏览
25

这个问题在这里已有答案:

我有一个集合 t1 ,其架构中包含以下字段

_id, field1, field1

我想设置 field2 的值 field1 像sql:

update t1 set field1=field2;

我如何在MongoDB中做到这一点?

3 回答

  • 10

    这里有好消息和坏消息 .

    坏消息是AFAIK你不能通过单个update()调用来做 - mongo不支持在更新中引用当前对象 .

    好消息是还有其他方法可以做到这一点,例如:你可以运行forEach循环:

    db.item.find(conditions...).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

  • 2

    从版本3.4开始,我们可以使用 $addFields 聚合管道运算符,而无需客户端处理,这是最有效的方法 .

    db.collection.aggregate(
        [
            { "$addFields": { "field2": "$field1" }},
            { "$out": "collection" }
        ]
    )
    

    在版本3.4之前,我们需要迭代 Cursor 对象并使用$set运算符添加具有现有"field1"值的新字段 . 您需要使用"bulk"操作来实现此目的,以实现最高效率 .

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

    这可以通过以下方式完成:

    db.nameOfCollection.find().forEach(
        function (elem) {
            db.nameOfCollection.update(
                {
                    _id: elem._id
                },
                {
                    $set: {
                        field2: elem.field1
                    }
                }
            );
        }
    );
    

相关问题