db.collection.bulkWrite()
드라이버가 포함된 MongoDB
이 페이지에서는 mongosh
메서드를 설명합니다. MongoDB 드라이버에서 해당 메서드를 보려면 프로그래밍 언어의 해당 페이지를 참조하세요.
정의
db.collection.bulkWrite()
실행 순서를 제어하여 여러 쓰기 작업을 수행합니다.
반환합니다: - 작업이 쓰기 고려로 실행된 경우 부울
acknowledged
를true
로, 쓰기 고려가 비활성화된 경우false
로 설정합니다. - 각 쓰기 작업의 개수입니다.
- 성공적으로 삽입되거나 업스트된 각 문서에 대해
_id
를 포함하는 배열입니다.
- 작업이 쓰기 고려로 실행된 경우 부울
호환성
db.collection.bulkWrite()
는 다음 환경에서 호스팅되는 배포에서 사용할 수 있습니다.
MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스
참고
이 명령은 모든 MongoDB Atlas 클러스터에서 지원됩니다. 모든 명령에 대한 Atlas 지원에 관해 자세히 알아보려면 지원되지 않는 명령을 참조하십시오.
MongoDB Enterprise: MongoDB의 구독 기반 자체 관리 버전
MongoDB Community: MongoDB의 소스 사용 가능 무료 자체 관리 버전
참고
Atlas UI 에서는 대량 쓰기 작업을 수행할 수 없습니다. 여러 문서를 삽입하려면 문서 배열을 삽입해야 합니다. 자세히 알아보려면 Atlas 문서에서 문서 생성, 보기, 업데이트 및 삭제를 참조하세요.
구문
bulkWrite()
메서드의 형식은 다음과 같습니다.
db.collection.bulkWrite( [ <operation 1>, <operation 2>, ... ], { writeConcern : <document>, ordered : <boolean> } )
bulkWrite()
메서드는 다음 매개변수를 사용합니다.
Parameter | 유형 | 설명 |
---|---|---|
| 배열 | |
| 문서 | 선택 사항입니다. 쓰기 고려를 표현하는 문서입니다. 기본 쓰기 고려를 사용하지 않으려면 생략하세요. 트랜잭션에서 실행되는 경우 작업에 대한 쓰기 고려를 명시적으로 설정하지 마세요. 트랜잭션에 쓰기 고려를 사용하려면 트랜잭션 및 쓰기 고려를 참조하세요. |
| 부울 |
행동
bulkWrite()
은 쓰기 작업의 배열을 가져와서 각 작업을 실행합니다. 기본적으로 작업은 순서대로 실행됩니다. 쓰기 작업 실행 순서를 제어하려면 작업 실행을 참조하세요.
쓰기 작업
insertOne
단일 문서를 collection에 삽입합니다.
db.collection.bulkWrite( [ { insertOne : { "document" : <document> } } ] )
updateOne 및 updateMany
updateOne
필터와 일치하는 컬렉션의 단일 문서를 업데이트합니다. 여러 문서가 일치하는 경우 updateOne
은 첫 번째 일치하는 문서만 업데이트합니다.
db.collection.bulkWrite( [ { updateOne : { "filter": <document>, "update": <document or pipeline>, "upsert": <boolean>, "collation": <document>, "arrayFilters": [ <filterdocument1>, ... ], "hint": <document|string> } } ] )
updateMany
필터와 일치하는 컬렉션의 모든 문서를 업데이트합니다.
db.collection.bulkWrite( [ { updateMany : { "filter" : <document>, "update" : <document or pipeline>, "upsert" : <boolean>, "collation": <document>, "arrayFilters": [ <filterdocument1>, ... ], "hint": <document|string> } } ] )
필드 | 참고 사항 |
---|---|
| 업데이트의 선택 기준입니다. 메서드와 동일한 쿼리 선택기를 |
| |
| 선택 사항. 업서트를 수행할지 여부를 나타내는 부울입니다. 기본적으로 |
| 선택 사항입니다. 필터 문서의 배열로, 배열 필드에 대한 업데이트 작업을 위해 수정할 배열 요소를 결정합니다. |
| 선택 사항입니다. 작업에 사용할 데이터 정렬을 지정합니다. |
| 선택 사항입니다. |
자세한 내용은 db.collection.updateOne()
및 db.collection.updateMany()
를 참조하세요.
replaceOne
replaceOne
컬렉션에서 필터와 일치하는 단일 문서를 대체합니다. 여러 문서가 일치하는 경우 replaceOne
은 첫 번째 일치하는 문서만 대체합니다.
db.collection.bulkWrite([ { replaceOne : { "filter" : <document>, "replacement" : <document>, "upsert" : <boolean>, "collation": <document>, "hint": <document|string> } } ] )
필드 | 참고 사항 |
---|---|
| 교체 작업의 선택 기준입니다. |
| 대체 문서입니다. 문서에는 업데이트 연산자가 포함될 수 없습니다. |
| 선택 사항. 업서트를 수행할지 여부를 나타내는 부울입니다. 기본적으로 |
| 선택 사항입니다. 작업에 사용할 데이터 정렬을 지정합니다. |
| 선택 사항입니다. |
자세한 내용은 db.collection.replaceOne()
을 참고하세요.
deleteOne과 deleteMany
deleteOne
은 필터와 일치하는 컬렉션의 단일 문서를 삭제합니다. 여러 문서가 일치하는 경우 deleteOne
은 첫 번째 일치하는 문서만 삭제합니다.
db.collection.bulkWrite([ { deleteOne : { "filter" : <document>, "collation" : <document> // Available starting in 3.4 } } ] )
deleteMany
필터와 일치하는 컬렉션의 모든 문서를 삭제합니다.
db.collection.bulkWrite([ { deleteMany: { "filter" : <document>, "collation" : <document> // Available starting in 3.4 } } ] )
필드 | 참고 사항 |
---|---|
| 삭제 작업의 선택 기준입니다. |
| 선택 사항입니다. 작업에 사용할 데이터 정렬을 지정합니다. |
자세한 내용은 db.collection.deleteOne()
및 db.collection.deleteMany()
를 참조하세요.
_id
필드
문서에 _id 필드가 지정되지 않은 경우 mongod
에서 _id
필드를 추가하고 삽입 또는 업서트하기 전에 문서에 고유한 ObjectId()
를 할당합니다. 대부분의 드라이버는 ObjectId를 생성하고 _id
필드를 삽입하지만, 드라이버나 애플리케이션이 수행하지 않는 경우 mongod
에서 _id
를 생성하여 채웁니다.
문서에 _id
필드가 포함된 경우 중복 키 오류를 방지하려면 _id
값이 컬렉션 내에서 고유해야 합니다.
업데이트 또는 교체 작업에서는 원본 문서와 다른 _id
값을 지정할 수 없습니다.
연산 실행
ordered
매개변수는 bulkWrite()
이 작업을 순서대로 실행할지 여부를 지정합니다. 기본적으로 작업은 순서대로 실행됩니다.
다음 코드는 연산이 5개 포함된 bulkWrite()
를 나타냅니다.
db.collection.bulkWrite( [ { insertOne : <document> }, { updateOne : <document> }, { updateMany : <document> }, { replaceOne : <document> }, { deleteOne : <document> }, { deleteMany : <document> } ] )
기본값 ordered : true
상태에서는 첫 번째 연산 insertOne
부터 마지막 연산 deleteMany
까지 각 연산이 순서대로 실행됩니다.
ordered
를 거짓으로 설정하면 성능을 높이기 위해 mongod
로 작업 순서를 변경할 수 있습니다. 애플리케이션은 작업 실행 순서에 의존해서는 안 됩니다.
다음 코드는 연산 6개가 포함된 정렬되지 않은 bulkWrite()
를 나타냅니다.
db.collection.bulkWrite( [ { insertOne : <document> }, { updateOne : <document> }, { updateMany : <document> }, { replaceOne : <document> }, { deleteOne : <document> }, { deleteMany : <document> } ], { ordered : false } )
ordered : false
을 사용하면 연산 결과가 달라질 수 있습니다. 예를 들어 deleteOne
또는 deleteMany
는 insertOne
, updateOne
, updateMany
또는 replaceOne
작업의 이전 또는 이후 실행 여부에 따라 더 많은 문서 또는 더 적은 문서를 제거할 수 있습니다.
각 그룹의 작업 수는 데이터베이스의 maxWriteBatchSize 값을 초과할 수 없습니다. maxWriteBatchSize
의 기본값은 100,000
입니다. 이 값은 hello.maxWriteBatchSize
필드에 표시됩니다.
이 제한은 오류 메시지의 크기가 너무 커지는 문제를 방지합니다. 그룹이 이 제한을 초과하면 클라이언트 드라이버는 그룹을 제한 값보다 작거나 같은 수의 작은 그룹으로 나눕니다. 예를 들어 maxWriteBatchSize
값이 100,000
인 경우 대기열이 200,000
개의 작업으로 구성되어 있으면 드라이버는 각각 100,000
개의 작업이 있는 2개의 그룹을 만듭니다.
참고
이 드라이버는 고급 API를 사용할 때에만 그룹을 작은 그룹 여러 개로 나눕니다. db.runCommand()
을(를) 직접 사용하면(예시: 드라이버를 작성할 때) 한도를 초과하는 쓰기 배치를 실행하려고 할 때 MongoDB에서 오류가 발생합니다.
단일 배치에 대한 오류 보고서가 너무 커지면 MongoDB는 나머지 모든 오류 메시지를 빈 문자열로 자릅니다. 총 크기가 1MB
보다 큰 오류 메시지가 두 개 이상 있으면 잘립니다.
크기 및 그룹화 메커니즘은 내부 성능 세부 정보이며 향후 버전에서 변경될 수 있습니다.
샤드 컬렉션에서 ordered
작업 목록을 실행하는 것은 unordered
목록을 실행하는 것보다 일반적으로 느립니다. 정렬된 목록에서는 각 작업이 이전 작업이 완료될 때까지 기다려야 하기 때문입니다.
고정 사이즈 컬렉션
bulkWrite()
쓰기 작업은 고정 사이즈 컬렉션에서 사용할 때 제한이 있습니다.
updateOne
및 updateMany
가 WriteError
를 발생시킵니다(update
기준으로 인해 수정되는 문서의 크기가 커지는 경우).
replaceOne
은 replacement
문서의 크기가 원본 문서보다 큰 경우 WriteError
를 발생시킵니다.
deleteOne
및 deleteMany
은(는) 고정 사이즈 컬렉션에 사용하면 WriteError
을(를) 발생시킵니다.
Time Series 컬렉션
bulkWrite()
쓰기 작업은 time series 컬렉션에서 사용할 때 제한이 있습니다. time series 컬렉션에는 insertOne
만 사용할 수 있습니다. 다른 모든 작업은 WriteError
를 반환합니다.
Error Handling
db.collection.bulkWrite()
는 오류 발생 시 BulkWriteError
예외를 발생시킵니다. 트랜잭션 내부의 오류 처리를 참조하세요.
쓰기 고려 오류를 제외하고 정렬된 작업은 오류 발생 후 중지되는 반면 정렬되지 않은 작업은 트랜잭션 내에서 실행되는 경우를 제외하고 대기열에 남아 있는 쓰기 작업을 계속 처리합니다. 트랜잭션 내부의 오류 처리를 참조하세요.
쓰기 고려 오류는 writeConcernErrors
필드에 표시되고 기타 모든 오류는 writeErrors
필드에 표시됩니다. 오류가 발생하면 입력된 _id
값 대신 성공한 쓰기 연산의 수가 표시됩니다. 순서가 지정된 연산에서는 발생한 단일 오류가 표시됩니다. 한편 순서가 지정되지 않은 연산에서는 각 오류가 한 배열에 표시됩니다.
스키마 유효성 검사 오류
컬렉션 에서 스키마 유효성 검사 를 사용하고 validationAction
이(가) error
(으)로 설정하다 경우 잘못된 문서 를 삽입하거나 잘못된 값으로 문서 를 업데이트하면 오류가 발생합니다. operations
배열 에서 유효하지 않은 연산 앞에 있는 연산이 실행되어 컬렉션 에 기록됩니다. ordered
필드 는 나머지 작업이 실행되는지 여부를 결정합니다.
트랜잭션
db.collection.bulkWrite()
는 분산 트랜잭션 내에서 사용할 수 있습니다.
중요
대부분의 경우 분산 트랜잭션은 단일 문서 쓰기에 비해 더 큰 성능 비용이 발생하므로 분산 트랜잭션의 가용성이 효과적인 스키마 설계를 대체할 수는 없습니다. 대부분의 시나리오에서 비정규화된 데이터 모델 (내장된 문서 및 배열) 은 계속해서 데이터 및 사용 사례에 최적일 것입니다. 즉, 대부분의 시나리오에서 데이터를 적절하게 모델링하면 분산 트랜잭션의 필요성이 최소화됩니다.
추가 트랜잭션 사용 고려 사항(예: 런타임 제한 및 oplog 크기 제한)은 프로덕션 고려사항을 참조하세요.
트랜잭션 내 삽입 및 업서트
기능 호환성 버전(fcv) "4.4"
이상의 경우, 존재하지 않는 컬렉션에 대해 트랜잭션에서 upsert: true
로 삽입 연산 또는 업데이트 연산을 실행하면 컬렉션이 암시적으로 생성됩니다.
참고
샤드 간 쓰기 트랜잭션에서는 새 컬렉션을 생성할 수 없습니다. 예를 들어, 하나의 샤드에서 기존 컬렉션에 쓰고 다른 샤드에서 암시적으로 새 컬렉션을 생성하는 경우, MongoDB는 동일한 트랜잭션에서 두 작업을 모두 수행할 수 없습니다.
쓰기 고려 및 트랜잭션
트랜잭션에서 실행되는 경우 작업에 대한 쓰기 고려를 명시적으로 설정하지 마세요. 트랜잭션에 쓰기 고려를 사용하려면 트랜잭션 및 쓰기 고려를 참조하세요.
트랜잭션 내부의 오류 처리하기
MongoDB 4.2부터 db.collection.bulkWrite()
연산이 트랜잭션 내부에서 오류가 발생하면 이 메서드는(트랜잭션 외부에서와 동일하게) BulkWriteException을 발생시킵니다.
4.0에서는 bulkWrite
연산의 트랜잭션 내부에서 오류가 발생할 경우, 발생한 오류가 BulkWriteException
(으)로 래핑되지 않습니다.
대량 쓰기의 순서가 지정되지 않은 경우에도 트랜잭션 내부에서는 대량 쓰기의 첫 오류로 인해 대량 쓰기 전체가 실패하고 트랜잭션이 중단됩니다.
예시
순서가 지정된 대량 쓰기 예시
bulkWrite()
작업 순서 및 오류 처리를 이해하는 것이 중요합니다. 기본적으로 bulkWrite()
(은)는 순서가 지정된 작업 목록을 실행합니다.
작업은 연속적으로 실행됩니다.
작업에 오류가 있는 경우 해당 작업과 이후 작업은 실행되지 않습니다.
오류 작업 이전에 나열된 작업이 완료되었습니다.
다음 bulkWrite()
예시에서는 pizzas
컬렉션을 사용합니다.
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
다음 bulkWrite()
예시에서는 이러한 작업을 pizzas
컬렉션에서 실행합니다.
0}을 사용하여 두 개의 문서를 추가합니다.
insertOne
0}을 사용하여 문서를 업데이트합니다.
updateOne
0}을(를) 사용하여 문서를 삭제합니다.
deleteOne
0}을 사용하여 문서를 바꿉니다.
replaceOne
try { db.pizzas.bulkWrite( [ { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } }, { insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } }, { updateOne: { filter: { type: "cheese" }, update: { $set: { price: 8 } } } }, { deleteOne: { filter: { type: "pepperoni"} } }, { replaceOne: { filter: { type: "vegan" }, replacement: { type: "tofu", size: "small", price: 4 } } } ] ) } catch( error ) { print( error ) }
완료된 작업의 요약을 포함하는 예시 출력:
{ acknowledged: true, insertedCount: 2, insertedIds: { '0': 3, '1': 4 }, matchedCount: 2, modifiedCount: 2, deletedCount: 1, upsertedCount: 0, upsertedIds: {} }
이전 bulkWrite()
예시를 실행하기 전에 컬렉션에 _id
가 4
인 문서가 이미 포함되어 있는 경우 두 번째 insertOne
작업에 대해 다음과 같은 중복 키 예외가 반환됩니다.
writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 4 }', op: { _id: 4, type: 'sausage', size: 'large', price: 10 } } } ], result: BulkWriteResult { result: { ok: 1, writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 4 }', op: { _id: 4, type: 'sausage', size: 'large', price: 10 } } } ], writeConcernErrors: [], insertedIds: [ { index: 0, _id: 3 }, { index: 1, _id: 4 } ], nInserted: 1, nUpserted: 0, nMatched: 0, nModified: 0, nRemoved: 0, upserted: [] } }
bulkWrite()
예시는 순서가 지정되어 있으므로 첫 번째 insertOne
작업만 완료됩니다.
오류가 없는 모든 작업을 완료하려면 ordered
를 false
로 설정한 상태에서 bulkWrite()
를 실행합니다. 예를 들어 다음 섹션을 참조하세요.
순서가 지정되지 않은 대량 쓰기 예시
순서가 지정되지 않은 bulkWrite()
를 지정하려면 ordered
를 false
로 설정합니다.
순서가 지정되지 않은 bulkWrite()
연산 목록에서:
작업은 병렬로 실행될 수 있습니다(보장되지 않음). 자세한 내용은 순서가 지정된 작업과 순서가 지정되지 않은 작업을 참조하세요.
오류가 있는 작업은 완료되지 않습니다.
오류 없이 모든 작업이 완료됩니다.
pizzas
collection 예시를 계속 진행하여 collection을 제거하고 다시 생성합니다.
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
다음 예시를 살펴보겠습니다.
bulkWrite()
는pizzas
컬렉션에서 순서가 지정되지 않은 작업을 실행합니다.두 번째
insertOne
작업에는 첫 번째insertOne
와 동일한_id
있으므로 중복 키 오류가 발생합니다.
try { db.pizzas.bulkWrite( [ { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } }, { insertOne: { document: { _id: 3, type: "sausage", size: "large", price: 10 } } }, { updateOne: { filter: { type: "cheese" }, update: { $set: { price: 8 } } } }, { deleteOne: { filter: { type: "pepperoni"} } }, { replaceOne: { filter: { type: "vegan" }, replacement: { type: "tofu", size: "small", price: 4 } } } ], { ordered: false } ) } catch( error ) { print( error ) }
중복 키 오류와 완료된 작업의 요약을 포함하는 예시 출력:
writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 3 }', op: { _id: 3, type: 'sausage', size: 'large', price: 10 } } } ], result: BulkWriteResult { result: { ok: 1, writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 3 }', op: { _id: 3, type: 'sausage', size: 'large', price: 10 } } } ], writeConcernErrors: [], insertedIds: [ { index: 0, _id: 3 }, { index: 1, _id: 3 } ], nInserted: 1, nUpserted: 0, nMatched: 2, nModified: 2, nRemoved: 1, upserted: [] } }
중복 키 오류로 인해 두 번째 insertOne
연산이 실패했습니다. 순서가 지정되지 않은 bulkWrite()
에서 오류가 없는 모든 작업이 완료됩니다.
쓰기 고려가 있는 대량 쓰기 예시
pizzas
collection 예시를 계속 진행하여 collection을 제거하고 다시 생성합니다.
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
다음 bulkWrite()
예시에서는 pizzas
컬렉션에서 작업을 실행하고 100밀리초의 시간 제한이 있는 "majority"
쓰기 고려를 설정합니다.
try { db.pizzas.bulkWrite( [ { updateMany: { filter: { size: "medium" }, update: { $inc: { price: 0.1 } } } }, { updateMany: { filter: { size: "small" }, update: { $inc: { price: -0.25 } } } }, { deleteMany: { filter: { size: "large" } } }, { insertOne: { document: { _id: 4, type: "sausage", size: "small", price: 12 } } } ], { writeConcern: { w: "majority", wtimeout: 100 } } ) } catch( error ) { print( error ) }
대부분의 복제본 세트 노드가 작업을 확인하는 데 걸리는 시간이 wtimeout
을 초과하는 경우 이 예시에서는 쓰기 고려 오류와 완료된 작업의 요약이 반환됩니다.
result: BulkWriteResult { result: { ok: 1, writeErrors: [], writeConcernErrors: [ WriteConcernError { err: { code: 64, codeName: 'WriteConcernFailed', errmsg: 'waiting for replication timed out', errInfo: { wtimeout: true, writeConcern: [Object] } } } ], insertedIds: [ { index: 3, _id: 4 } ], nInserted: 0, nUpserted: 0, nMatched: 2, nModified: 2, nRemoved: 0, upserted: [], opTime: { ts: Timestamp({ t: 1660329086, i: 2 }), t: Long("1") } } }