복붙노트

[MONGODB] 다른 필드의 업데이트 MongoDB의 필드를 사용하여 값

MONGODB

다른 필드의 업데이트 MongoDB의 필드를 사용하여 값

MongoDB에에서, 다른 필드로부터의 값을 이용하여, 필드의 값을 갱신 할 수있다? 동등한 SQL 같은 것입니다 :

UPDATE Person SET Name = FirstName + ' ' + LastName

그리고 MongoDB의 의사 코드는 다음과 같습니다

db.person.update( {}, { $set : { name : firstName + ' ' + lastName } );

해결법

  1. ==============================

    1.이 작업을 수행하는 가장 좋은 방법은 업데이트 문서의 통합 파이프 라인과 updateOne, updateMany 또는 업데이트 수집 방법의 사용 허용 버전 4.2 이상이다. 모든 언어 드라이버를하지 않을 경우, 후자는 대부분 더 이상 사용되지 않습니다.

    이 작업을 수행하는 가장 좋은 방법은 업데이트 문서의 통합 파이프 라인과 updateOne, updateMany 또는 업데이트 수집 방법의 사용 허용 버전 4.2 이상이다. 모든 언어 드라이버를하지 않을 경우, 후자는 대부분 더 이상 사용되지 않습니다.

    버전 4.2은 $ addFields의 별칭 인 $ 세트 파이프 라인 단계 연산자를 도입했다. 우리가 달성하려고하는 것과 매핑으로 여기 $ 세트를 사용합니다.

    db.collection.<update method>(
        {},
        [
            {"$set": {"name": { "$concat": ["$firstName", " ", "$lastName"]}}}
        ]
    )
    

    3.4 이상에서는 $ addFields 및 통합 파이프 라인 운영자 밖으로 $를 사용할 수 있습니다.

    db.collection.aggregate(
        [
            { "$addFields": { 
                "name": { "$concat": [ "$firstName", " ", "$lastName" ] } 
            }},
            { "$out": "collection" }
        ]
    )
    

    이 컬렉션을 업데이트하는 대신 기존의 모음을 교체하거나 새로 만들하지 않습니다. 또한 클라이언트 측 처리를해야하고, 작업에 따라 할 것이다 "타입 캐스팅"을 요구하는 업데이트 작업을 위해, 대신 .aggreate () 메서드의 발견 () 메소드를 사용해야 할 수도 있습니다.

    우리는이 작업을 수행하는 방법은 $ 우리의 문서를 투사하고 연결된 문자열을 반환 $의 CONCAT 문자열 집계 연산자를 사용하는 것입니다. 우리는 거기를에서, 당신은 그 반복 처리 커서와 최대 효율을 위해 대량 작업을 사용하여 문서에 새로운 필드를 추가하기 위해 $ 세트 업데이트 연산자를 사용합니다.

    var cursor = db.collection.aggregate([ 
        { "$project":  { 
            "name": { "$concat": [ "$firstName", " ", "$lastName" ] } 
        }}
    ])
    

    이에서, 당신은 bulkWrite 방법을 사용해야합니다.

    var requests = [];
    cursor.forEach(document => { 
        requests.push( { 
            'updateOne': {
                'filter': { '_id': document._id },
                'update': { '$set': { 'name': document.name } }
            }
        });
        if (requests.length === 500) {
            //Execute per 500 operations and re-init
            db.collection.bulkWrite(requests);
            requests = [];
        }
    });
    
    if(requests.length > 0) {
         db.collection.bulkWrite(requests);
    }
    

    이 버전에서 당신은 지금은 사용되지 않는 대량 API 및 관련 방법을 사용해야합니다.

    var bulk = db.collection.initializeUnorderedBulkOp();
    var count = 0;
    
    cursor.snapshot().forEach(function(document) { 
        bulk.find({ '_id': document._id }).updateOne( {
            '$set': { 'name': document.name }
        });
        count++;
        if(count%500 === 0) {
            // Excecute per 500 operations and re-init
            bulk.execute();
            bulk = db.collection.initializeUnorderedBulkOp();
        }
    })
    
    // clean up queues
    if(count > 0) {
        bulk.execute();
    }
    
    cursor["result"].forEach(function(document) {
        db.collection.update(
            { "_id": document._id }, 
            { "$set": { "name": document.name } }
        );
    })
    
  2. ==============================

    2.당신은을 통해 반복해야한다. 특정 사건의 경우 :

    당신은을 통해 반복해야한다. 특정 사건의 경우 :

    db.person.find().snapshot().forEach(
        function (elem) {
            db.person.update(
                {
                    _id: elem._id
                },
                {
                    $set: {
                        name: elem.firstname + ' ' + elem.lastname
                    }
                }
            );
        }
    );
    
  3. ==============================

    3.분명히 효율적으로 MongoDB를 3.4 이후, styvane의 답변을 참조 할 수있는 방법이있다.

    분명히 효율적으로 MongoDB를 3.4 이후, styvane의 답변을 참조 할 수있는 방법이있다.

    아래의 폐기 대답

    당신은 (아직) 업데이 트에있는 문서 자체를 참조 할 수 없습니다. 당신은 문서를 반복 할 필요 기능을 사용하여 각 문서를 업데이트 할 수 있습니다. 예를 들어이 대답하거나 서버 측 평가에 대한이 하나 ()를 참조하십시오.

  4. ==============================

    4.높은 활성을 가진 데이터베이스의 경우) (당신의 업데이트가 적극적으로 변화 기록에 영향을 미칠 이런 이유로 나는 스냅 샷을 사용하는 것이 좋습니다 문제로 실행할 수 있습니다

    높은 활성을 가진 데이터베이스의 경우) (당신의 업데이트가 적극적으로 변화 기록에 영향을 미칠 이런 이유로 나는 스냅 샷을 사용하는 것이 좋습니다 문제로 실행할 수 있습니다

    db.person.find().snapshot().forEach( function (hombre) {
        hombre.name = hombre.firstName + ' ' + hombre.lastName; 
        db.person.save(hombre); 
    });
    

    http://docs.mongodb.org/manual/reference/method/cursor.snapshot/

  5. ==============================

    5.나는 위의 솔루션을 시도했지만 나는 많은 양의 데이터에 대한 부적합 발견했다. 그때 스트림 기능을 발견 :

    나는 위의 솔루션을 시도했지만 나는 많은 양의 데이터에 대한 부적합 발견했다. 그때 스트림 기능을 발견 :

    MongoClient.connect("...", function(err, db){
        var c = db.collection('yourCollection');
        var s = c.find({/* your query */}).stream();
        s.on('data', function(doc){
            c.update({_id: doc._id}, {$set: {name : doc.firstName + ' ' + doc.lastName}}, function(err, result) { /* result == true? */} }
        });
        s.on('end', function(){
            // stream can end before all your updates do if you have a lot
        })
    })
    
  6. ==============================

    6.이 응답에 대해 스냅 기능이 업데이트에 따라, 버전 3.6에서 중단된다. 그래서, 버전 3.6 이상에서,이 동작이 방법을 수행 할 수있다 :

    이 응답에 대해 스냅 기능이 업데이트에 따라, 버전 3.6에서 중단된다. 그래서, 버전 3.6 이상에서,이 동작이 방법을 수행 할 수있다 :

    db.person.find().forEach(
        function (elem) {
            db.person.update(
                {
                    _id: elem._id
                },
                {
                    $set: {
                        name: elem.firstname + ' ' + elem.lastname
                    }
                }
            );
        }
    );
    
  7. ==============================

    7.몽고 4.2 시작, db.collection.update ()는 마지막으로 다른 필드를 기준으로 필드의 업데이트 / 생성을 허용 집계 파이프 라인을 받아 들일 수 있습니다 :

    몽고 4.2 시작, db.collection.update ()는 마지막으로 다른 필드를 기준으로 필드의 업데이트 / 생성을 허용 집계 파이프 라인을 받아 들일 수 있습니다 :

    // { firstName: "Hello", lastName: "World" }
    db.collection.update(
      {},
      [{ $set: { name: { $concat: [ "$firstName", " ", "$lastName" ] } } }],
      { multi: true }
    )
    // { "firstName" : "Hello", "lastName" : "World", "name" : "Hello World" }
    
  8. ==============================

    8.여기에 우리가 ~ 150_000 기록을 위해 다른 하나 개의 필드를 복사 해낸거야. 이 육분에 대한 걸렸지 만 훨씬 적은은 루비 객체의 같은 수의 반복을 인스턴스화 할 수 있었고 것보다 리소스를 많이 아직도있다.

    여기에 우리가 ~ 150_000 기록을 위해 다른 하나 개의 필드를 복사 해낸거야. 이 육분에 대한 걸렸지 만 훨씬 적은은 루비 객체의 같은 수의 반복을 인스턴스화 할 수 있었고 것보다 리소스를 많이 아직도있다.

    js_query = %({
      $or : [
        {
          'settings.mobile_notifications' : { $exists : false },
          'settings.mobile_admin_notifications' : { $exists : false }
        }
      ]
    })
    
    js_for_each = %(function(user) {
      if (!user.settings.hasOwnProperty('mobile_notifications')) {
        user.settings.mobile_notifications = user.settings.email_notifications;
      }
      if (!user.settings.hasOwnProperty('mobile_admin_notifications')) {
        user.settings.mobile_admin_notifications = user.settings.email_admin_notifications;
      }
      db.users.save(user);
    })
    
    js = "db.users.find(#{js_query}).forEach(#{js_for_each});"
    Mongoid::Sessions.default.command('$eval' => js)
    
  9. from https://stackoverflow.com/questions/3974985/update-mongodb-field-using-value-of-another-field by cc-by-sa and MIT license