MongoDB에서 $set과 $push를 한 번에 사용하기
MongoDB에서는 하나의 업데이트 작업 안에서 $set 연산자와 $push 연산자를 동시에 사용할 수 있습니다. $set은 기존 필드의 값을 수정하거나 새로 설정할 때 사용되고, $push는 배열 필드에 새로운 요소를 추가할 때 사용됩니다. 두 연산자를 같은 업데이트 문서에 나란히 작성하기만 하면 되며, 별도로 업데이트 명령을 두 번 실행할 필요가 없습니다.
아래 예제를 통해 실제 동작 과정을 단계별로 살펴보겠습니다.
1단계: 컬렉션 생성 및 문서 삽입
먼저 insertOne() 메서드를 사용해 테스트용 컬렉션에 문서를 삽입합니다.
> db.dem0143.insertOne({"StudentId":1,"Details":{"Name":"Chris"}});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e32eb9efdf09dd6d08539b7")
}
> db.dem0143.insertOne({"StudentId":2,"Details":{"Name":"David"}});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e32eba5fdf09dd6d08539b8")
}
2단계: 삽입된 문서 확인
find() 메서드를 사용하여 컬렉션의 모든 문서를 조회합니다.
> db.dem0143.find();
위 쿼리는 다음과 같은 결과를 출력합니다.
{ "_id" : ObjectId("5e32eb9efdf09dd6d08539b7"), "StudentId" : 1, "Details" : { "Name" : "Chris" } }
{ "_id" : ObjectId("5e32eba5fdf09dd6d08539b8"), "StudentId" : 2, "Details" : { "Name" : "David" } }
3단계: 단일 업데이트에서 $set과 $push 함께 사용
다음 쿼리는 하나의 update() 호출 안에서 $push로 StudentAge 배열에 값 21을 추가하고, 동시에 $set으로 Details.Name 필드의 값을 "John Doe"로 변경합니다.
> db.dem0143.update({_id: ObjectId("5e32eba5fdf09dd6d08539b8")}, {$push: {StudentAge:21}, $set: {"Details.Name":"John Doe"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
실행 결과에서 nMatched가 1, nModified가 1로 표시되는데, 이는 조건에 일치하는 문서 한 개가 성공적으로 수정되었음을 의미합니다.
4단계: 업데이트 결과 확인
다시 find() 메서드로 전체 문서를 조회하여 변경 사항을 확인합니다.
> db.dem0143.find();
출력 결과는 다음과 같습니다.
{ "_id" : ObjectId("5e32eb9efdf09dd6d08539b7"), "StudentId" : 1, "Details" : { "Name" : "Chris" } }
{ "_id" : ObjectId("5e32eba5fdf09dd6d08539b8"), "StudentId" : 2, "Details" : { "Name" : "John Doe" }, "StudentAge" : [ 21 ] }
결과를 보면 StudentId가 2인 문서에서 Name 필드가 "David"에서 "John Doe"로 변경되었고($set), 새로운 배열 필드인 StudentAge가 생성되며 값 21이 추가된 것($push)을 확인할 수 있습니다.
참고: 최신 MongoDB 버전에서는 updateOne() 사용 권장
update() 메서드는 구버전 방식으로, 조건에 일치하는 문서가 여러 개일 때 첫 번째 문서만 수정한다는 특성 때문에 현재는 사용이 권고되지 않습니다(deprecated). 최신 버전에서는 단일 문서 수정 시 updateOne(), 여러 문서 수정 시 updateMany()를 사용하는 것이 좋습니다. 위와 동일한 업데이트는 다음과 같이 작성할 수 있습니다.
> db.dem0143.updateOne({_id: ObjectId("5e32eba5fdf09dd6d08539b8")}, {$push: {StudentAge:21}, $set: {"Details.Name":"John Doe"}});
정리하면, $set과 $push는 서로 다른 필드를 대상으로 할 경우 충돌 없이 하나의 업데이트 문서에 함께 사용할 수 있습니다. 이를 활용하면 데이터베이스에 보내는 요청 횟수를 줄일 수 있고, MongoDB의 원자성(atomicity) 보장 덕분에 두 연산이 한 번에 안전하게 적용된다는 장점도 있습니다.