본문 바로가기

MongoDB

[MongoDB] CRUD 쿼리사용 - BulkWrite

BulkWrite는 MongoDB 데이터 변경 명령( INSERT, UPDATE, REMOVE( DELETE ) )을 모아서 한 번에 실행할 수 있는 명령이다.

 

BulkWrite 명령은 다음과 같이 다양한 명령을 한 번에 모아서 실행할 수 있는데, 반드시 하나의 컬렉션에 대해서만 데이터를 변경할 수 있다.

 

   ① insertOne    ② updateOne    ③ updateMany
   ④ replaceOne    ⑤ deleteOne    ⑥ deleteMany

 

간단히 BulkWrite 명령의 예제를 한번 살펴보자.

 

다음 예제는 characters 컬렉션의 데이터를 변경하는 여러가지 명령을 한번에 모아서 실행하는 방법을 보여주고 있다.

 

mongo> db.characters.bulkWrite(
  [
    {
      insertOne : {
        "document" : {
          "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
        }
      }
    }
    , {
      insertOne : {
        "document" : {
          "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
        }
      }
    }, {
      updateOne : {
        "filter" : { "char" : "Eldon" }
      , "update" : { $set : { "status" : "Critical Injury" } }
      }
    }, {
      deleteOne : {
        "filter" : { "char" : "Brisbane" }
      }
    }, {
      replaceOne : {
          "filter" : { "char" : "Meldane" }
        , "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
      }
    }
  ]
);

{
      "acknowledged" : true
    , "deletedCount" : 0
    , "insertedCount" : 2
    , "matchedCount" : 0
    , "upsertedCount" : 0
    , "insertedIds" : {
    	  "0" : 4
    	, "1" : 5
    }
    , "upsertedIds" : { }
}

 

BulkWrite 명령의 결과는 INSERT와 UPDATE 그리고 DELETE 등의 명령 단위로 정리해서 적용된 건수를 보여준다.

 

처리 결과 insertedIds 서브 도큐먼트에서는 INSERT된 도큐먼트들의 프라이머리키( _id )값을 반환하며,

 

upsertedIds 서브 도큐먼트에는 UPDATE 명령의 upsert 플래그가 true일때 INSERT 된 도큐먼트들의 프라이머리 키( _id )를 반환한다.

 

위 예제처럼 직접 사용자가 프라이머리 키를 설정하는 경우에는 크게 중요하지 않지만,

 

MongoDB 드라이버나 라우터가 ObjectId를 생성해서 프라이머리 키를 설정하는 경우에는

 

저장된 도큐먼트를 다시 쿼리하지 않고 알아낼 수 있다.

 

BulkWrite 명령에 입력하는 각 하위 명령은 각자의 도큐먼트 포맷을 가지는데,

 

이는 MongoDB 메뉴얼( http://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite )에서 확인 할 수 있다.

 

 

BulkWrite 명령을 실행하는 도중에 에러가 발생하면 다음과 같이 BulkWriteError가 반환된다.

BulkWriteError(
  {
    "writeErrors" : [
      {
          "index" : 2
        , "code" : 11000
        , "errmsg" : "E11000 duplicate key error collection: testDB.characters index: _id_ dup key: { _id: 4.0 }"
        , "op" : {
            "_id" : 4
          , "char" : "Dithras"
          , "class" : "barbarian"
          , "lvl" : 4
          }
      }
    ]
    , "writeConcernErrors" : [ ]
    , "nInserted" : 0
    , "nUpserted" : 0
    , "nMatched" : 1
    , "nModified" : 1
    , "nRemoved" : 1
    , "upserted" : [ ]
  }
)

 

위 결과에서는 INSERT 하는 도큐먼트가 이미 존재해서 INSERT에 실패했다는 것을 알 수 있다.

 

그리고 삭제된 도큐먼트가 1건이며 새롭게 INSERT 된 도큐먼트도 1건이라는 것도 확인할 수 있다.

 

즉 BulkWrite 명령의 실행 결과로 UPDATE와 DELETE가 각각 1건씩 실행됐으며, 기 이후 INSERT가 실행됐는데

 

실행 도중 중복 키 에러가 발생하면서 BulkWrite가 실패했다는 것을 알 수 있다.

 

 

BulkWrite 명령도 다른 CRUD 멸령과 같이 ordered 옵션을 사용할 수 있다.

 

이때 ordered 옵션이 true이면 BulkWrite 명령에 주어진 각 하위 명령이 순차적으로 실행되며,

 

중간에 실패 도큐먼트가 발생하면 지금까지 변경된 도큐먼트는 그대로 유지하고 남은 작업은 모두 포기하고 멈춘다.

 

즉 RDBMS의 롤백과 같은 작업은 없다.

 

ordered 옵션을 false로 설정하면 MongoDB 서버는 BulkWrite의 각단위 작업을 여러 쓰레드로 나누어 병렬로 처리하게 되며,

 

중간에 에러가 발생해도 나머지 작업을 멈추지 않고 모두 처리한다.

 

mongo> db.characters.bulWrite(
  [
    {
      insertOne : {
        "document" : { "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3 }
      }
    }, {
      updateOne : {
          "filter" : { "char" : "Eldon" }
        , "update" : { "$set" : { "status" : "Critical Injury" } }
      }
    }
  ],
  { ordered : false }
)

 

ordered 옵션은 단순히 각 하위 명령의 실행 순서만 결정하는 것은 아니라,

 

머리 쓰레드로 병렬 처리를 할 수 있는지까지 결정한다.

 

만약 MongoDB 라우터를 사용해야 하는 샤드 클러스터 환경이라면 ordered 옵션으로 설정하면

 

MongoDB 라우터는 샤드의 개수와 무관하게 BulkWrite의 하위 명령을 하나씩 하나씩 차례대로 실행할 수밖에 없다.

 

하지만 ordered 옵션을 false로 설정하면 MongoDB 라우터는

 

BulkWrite의 하위 명령을 멀티 쓰레드로 여러 샤드에서 동시에 실행되게 한다.

 

mongo> db.chracters.bulkWrite(
  [
    {
      inserOne :{
        "document" : {
          "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
        }
      }
    }
  ],
  { ordered : false, writeConcern : { w : "majority", wtimeout : 100 } }
)

{
    "acknowledged" : true
  , "deletedCount" : 0
  , "insertedCount" : 0
  , "matchedCount" : 0
  , "upsertedCount" : 0
  , "insertedIds" : { }
  , "upsertedIds" : { }
}

 

 

출처 : https://wikibook.co.kr/real-mongodb/

 

Real MongoDB: 대용량 데이터 처리를 위한

MongoDB의 "Know-How"가 아닌 "Know-Why"를 전달해 드립니다! MongoDB 메뉴얼은 아주 간결하고 기본적인 내용에 충실하게 작성되어 있다. 하지만 문법이나 명령만으로는 DBMS를 사용할 수 없다. 내부 작동 ��

wikibook.co.kr