Computer >> 컴퓨터 >  >> 프로그래밍 >> MongoDB

MongoDB Upsert 완벽 가이드: 값이 고유하면 삽입하고, 이미 존재하면 업데이트하기

MongoDB에서 데이터를 다룰 때 upsert 옵션을 활용하면 매우 편리합니다. upsert는 'update'와 'insert'를 합친 개념으로, 삽입하려는 값이 컬렉션에 이미 존재하면 해당 문서를 업데이트하고, 존재하지 않으면 새로운 문서로 삽입합니다.

테스트용 컬렉션 생성하기

먼저 문서가 포함된 컬렉션을 생성해 보겠습니다.

> db.onlyInsertIfValueIsUniqueDemo.insertOne({"StudentName":"Larry","StudentAge":22});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c9a633815e86fd1496b38a4")
}
> db.onlyInsertIfValueIsUniqueDemo.insertOne({"StudentName":"Mike","StudentAge":21});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c9a634a15e86fd1496b38a5")
}
> db.onlyInsertIfValueIsUniqueDemo.insertOne({"StudentName":"Sam","StudentAge":24});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c9a635015e86fd1496b38a6")
}

이제 find() 메서드를 사용하여 컬렉션의 모든 문서를 조회해 보겠습니다.

> db.onlyInsertIfValueIsUniqueDemo.find().pretty();

위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.

{
   "_id" : ObjectId("5c9a633815e86fd1496b38a4"),
   "StudentName" : "Larry",
   "StudentAge" : 22
}
{
   "_id" : ObjectId("5c9a634a15e86fd1496b38a5"),
   "StudentName" : "Mike",
   "StudentAge" : 21
}
{
   "_id" : ObjectId("5c9a635015e86fd1496b38a6"),
   "StudentName" : "Sam",
   "StudentAge" : 24
}

Case 1: 값이 이미 존재하는 경우 → 업데이트 수행

삽입하려는 값이 이미 컬렉션에 존재한다면, 새 문서가 추가되지 않고 기존 문서가 업데이트됩니다. 아래 쿼리를 확인해 보세요.

> db.onlyInsertIfValueIsUniqueDemo.update({StudentName:"Mike"},{$set:{"StudentAge":27}},{ upsert: true});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

결과를 보면 nMatched : 1, nModified : 1로 표시되어, 조건에 일치하는 기존 문서(Mike)가 수정되었음을 알 수 있습니다. 다시 전체 문서를 조회해 확인해 보겠습니다.

> db.onlyInsertIfValueIsUniqueDemo.find().pretty();

실행 결과는 다음과 같습니다.

{
   "_id" : ObjectId("5c9a633815e86fd1496b38a4"),
   "StudentName" : "Larry",
   "StudentAge" : 22
}
{
   "_id" : ObjectId("5c9a634a15e86fd1496b38a5"),
   "StudentName" : "Mike",
   "StudentAge" : 27
}
{
   "_id" : ObjectId("5c9a635015e86fd1496b38a6"),
   "StudentName" : "Sam",
   "StudentAge" : 24
}

Mike의 나이가 21에서 27로 변경된 것을 확인할 수 있습니다. 즉, 값이 이미 존재했기 때문에 삽입 대신 업데이트가 수행된 것입니다.

Case 2: 값이 고유한 경우 → 새로 삽입 수행

반대로 삽입하려는 값이 컬렉션에 존재하지 않는다면, 새로운 문서로 삽입됩니다. 아래 쿼리를 살펴보겠습니다.

> db.onlyInsertIfValueIsUniqueDemo.update({StudentName:"David"},{$set:{"StudentAge":25}},{ upsert: true});
WriteResult({
   "nMatched" : 0,
   "nUpserted" : 1,
   "nModified" : 0,
   "_id" : ObjectId("5c9a654ce628c11759caea54")
})

이번에는 nMatched : 0, nUpserted : 1로 표시됩니다. 이는 일치하는 기존 문서가 없어서 새 문서가 삽입되었다는 의미입니다. 전체 문서를 다시 조회해 보겠습니다.

> db.onlyInsertIfValueIsUniqueDemo.find().pretty();

실행 결과는 다음과 같습니다.

{
   "_id" : ObjectId("5c9a633815e86fd1496b38a4"),
   "StudentName" : "Larry",
   "StudentAge" : 22
}
{
   "_id" : ObjectId("5c9a634a15e86fd1496b38a5"),
   "StudentName" : "Mike",
   "StudentAge" : 27
}
{
   "_id" : ObjectId("5c9a635015e86fd1496b38a6"),
   "StudentName" : "Sam",
   "StudentAge" : 24
}
{
   "_id" : ObjectId("5c9a654ce628c11759caea54"),
   "StudentName" : "David",
   "StudentAge" : 25
}

David라는 새로운 학생 문서가 성공적으로 삽입된 것을 확인할 수 있습니다.

정리 및 참고 사항

upsert 옵션의 동작 방식을 요약하면 다음과 같습니다.

  • 조건에 맞는 문서가 존재하는 경우: 기존 문서를 업데이트합니다. (nMatched : 1)
  • 조건에 맞는 문서가 없는 경우: 새 문서를 삽입합니다. (nUpserted : 1)

참고로 위 예제에서 사용한 update() 메서드는 구버전 문법입니다. MongoDB 3.2 이상 버전에서는 하나의 문서만 수정하는 updateOne(), 여러 문서를 수정하는 updateMany() 사용이 권장되며, 두 메서드 모두 동일하게 { upsert: true } 옵션을 지원합니다. 또한 MongoDB 4.2부터는 replaceOne()과 함께 사용하거나 집계 파이프라인 기반 업데이트도 가능하므로, 최신 환경에서는 이러한 메서드를 활용하는 것이 좋습니다.