web-dev-qa-db-ja.com

ドキュメント内の別のフィールドの値でフィールドを更新します

コレクションがありますt1スキーマに次のフィールドがあります

_id, field1, field1

セットしたいfield2の値field1のようなsql:

update t1 set field1=field2;

MongoDBでそれを行うにはどうすればよいですか?

28
firefox01

ここで良いニュースと悪いニュース。

悪い知らせは、私の知る限り、1回のupdate()呼び出しでは実行できないことです。mongoは、更新中の現在のオブジェクトの参照をサポートしていません。

良いニュースは、それを行うには他の方法があることです。 forEachループを実行できます。

db.item.find(conditions...).forEach( function (doc) {
  doc.field1 = doc.field2; 
  db.item.save(doc); 
});

ForEachは、管理シェル( 'mongo'コマンド)で実行するか、特定のドライバーのいくつかのメソッドを使用して実行できます(例:PHP in mongodb.execute( )ここで説明されているとおり: http://www.php.net/manual/en/mongodb.execute.php

37
Jakub P.

バージョン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 AP​​Iを使用できます。

_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();
}
_
11
styvane

これは次の方法で実行できます。

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