수색…


비고

단일 콜렉션에 대해 대량으로 수행 할 쓰기 조작 목록 작성.

필드를 다른 유형으로 변환하고 전체 모음을 대량으로 업데이트

일반적으로 필드 유형을 다른 것으로 변경하려는 경우, 예를 들어 원래 컬렉션에 문자열로 저장된 "숫자"또는 "날짜"필드가있을 수 있습니다.

{
    "name": "Alice",
    "salary": "57871",
    "dob": "1986-08-21"
},
{
    "name": "Bob",
    "salary": "48974",
    "dob": "1990-11-04"
}

목표는 위와 같은 엄청난 컬렉션을 업데이트하는 것입니다.

{
    "name": "Alice",
    "salary": 57871,
    "dob": ISODate("1986-08-21T00:00:00.000Z")
},
{
    "name": "Bob",
    "salary": 48974,
    "dob": ISODate("1990-11-04T00:00:00.000Z")
}

상대적으로 작은 데이터의 경우, 커서의 forEach() 메소드를 사용하여 snapshot 을 사용하여 콜렉션을 반복하고 다음과 같이 각 문서를 업데이트함으로써 위의 사항을 달성 할 수 있습니다.

db.test.find({
    "salary": { "$exists": true, "$type": 2 },
    "dob": { "$exists": true, "$type": 2 }
}).snapshot().forEach(function(doc){ 
    var newSalary = parseInt(doc.salary),
        newDob = new ISODate(doc.dob);        
    db.test.updateOne(
        { "_id": doc._id },
        { "$set": { "salary": newSalary, "dob": newDob } }
    );
});

작은 컬렉션의 경우에는 최적이지만 대용량 데이터 집합을 반복하고 서버에 대한 요청마다 각 업데이트 작업을 보내면 계산상의 불이익이 발생하므로 대규모 컬렉션의 성능이 크게 저하됩니다.

Bulk() API는 쓰기 작업이 대량으로 한 번만 서버에 전송되기 때문에 구조 작업을 수행하고 성능을 크게 향상시킵니다. 이 메서드는 forEach() 루프 내의 현재 업데이트 문과 같이 서버에 모든 쓰기 요청을 보내지 않지만 1000 건의 요청마다 한 번만 수행하므로 현재보다 훨씬 효율적이고 신속한 업데이트가 가능하므로 효율성이 달성됩니다.


위의 동일한 개념을 forEach() 루프와 함께 사용하여 배치를 만들면 다음과 같이 대량으로 컬렉션을 업데이트 할 수 있습니다. 이 데모에서 MongoDB 버전 >= 2.6< 3.2 에서 사용할 수있는 Bulk() API는 initializeUnorderedBulkOp() 메소드를 사용하여 배치에서 쓰기 작업을 비 결정적 순서와 함께 병렬로 실행합니다.

salarydob 필드를 각각 numericaldatetime 값으로 변경하여 clients 콜렉션의 모든 문서를 업데이트합니다.

var bulk = db.test.initializeUnorderedBulkOp(),
    counter = 0; // counter to keep track of the batch update size

db.test.find({
    "salary": { "$exists": true, "$type": 2 },
    "dob": { "$exists": true, "$type": 2 }
}).snapshot().forEach(function(doc){ 
    var newSalary = parseInt(doc.salary),
        newDob = new ISODate(doc.dob);
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "salary": newSalary, "dob": newDob }
    });

    counter++; // increment counter
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.test.initializeUnorderedBulkOp();
    }
});

다음 예제는 새로운 MongoDB 버전 3.2 적용됩니다.이 버전은 이후 Bulk() API를 더 이상 사용하지 않으며 bulkWrite() 사용하여 더 새로운 apis 세트를 제공합니다.

위와 동일한 커서를 사용하지만 동일한 forEach() 커서 메서드를 사용하여 대량 작업으로 배열을 만들어 각 대량 쓰기 문서를 배열에 푸시합니다. 쓰기 명령은 1000 개가 넘는 연산을 받아 들일 수 있기 때문에 루프를 1000 번 반복 할 때 작업을 그룹화하여 최대 1000 번의 작업을 수행하고 어레이를 다시 초기화해야합니다.

var cursor = db.test.find({
        "salary": { "$exists": true, "$type": 2 },
        "dob": { "$exists": true, "$type": 2 }
    }),
    bulkUpdateOps = [];

cursor.snapshot().forEach(function(doc){ 
    var newSalary = parseInt(doc.salary),
        newDob = new ISODate(doc.dob);
    bulkUpdateOps.push({ 
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": { "$set": { "salary": newSalary, "dob": newDob } }
         }
    });

    if (bulkUpdateOps.length === 1000) {
        db.test.bulkWrite(bulkUpdateOps);
        bulkUpdateOps = [];
    }
});         

if (bulkUpdateOps.length > 0) { db.test.bulkWrite(bulkUpdateOps); }


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow