MongoDB에서 문서 배열의 객체를 업데이트하는 방법
MongoDB에서 문서(document) 내부에 포함된 배열(array)의 객체를 수정하려면 update() 메서드를 사용해야 합니다. 특히 위치 연산자(positional operator)인 $와 함께 사용하면, 조건에 일치하는 특정 배열 요소만 정확하게 업데이트할 수 있습니다.
update() 메서드의 동작을 이해하기 위해 먼저 샘플 컬렉션과 문서를 생성해 보겠습니다.
1. 테스트용 컬렉션 생성
다음 쿼리는 고객 정보와 아이템 상세 내역을 담은 문서를 삽입합니다.
> db.updateObjects.insertOne({"CustomerId":1,"CustomerName":"Larry","TotalItems":100,
... "ItemDetails":[
... {
... "NameOfItem":"Item_1",
... "Amount":450
... },
... {
... "NameOfItem":"Item_2",
... "Amount":500
... },
... {
... "NameOfItem":"Item_3",
... "Amount":200
... }
... ]
... }
... );실행 결과는 다음과 같습니다.
{
"acknowledged" : true,
"insertedId" : ObjectId("5c6d688b0c3d5054b766a769")
}2. find() 메서드로 문서 조회
생성된 컬렉션의 문서는 find() 메서드로 확인할 수 있습니다.
> db.updateObjects.find().pretty();
위 쿼리의 출력 결과입니다.
{
"_id" : ObjectId("5c6d688b0c3d5054b766a769"),
"CustomerId" : 1,
"CustomerName" : "Larry",
"TotalItems" : 100,
"ItemDetails" : [
{
"NameOfItem" : "Item_1",
"Amount" : 450
},
{
"NameOfItem" : "Item_2",
"Amount" : 500
},
{
"NameOfItem" : "Item_3",
"Amount" : 200
}
]
}3. $inc 연산자와 위치 연산자($)로 중첩 업데이트 수행
이제 NameOfItem이 "Item_3"인 객체의 Amount 필드(현재 값 200)를 130만큼 증가시켜 보겠습니다. 이때 값의 증감에는 $inc 연산자를 사용하고, 조건에 매칭된 배열 요소를 지정하기 위해 위치 연산자($)를 활용합니다.
> db.updateObjects.update({"CustomerId":1,"ItemDetails.NameOfItem":"Item_3"},
{$inc:{"ItemDetails.$.Amount":130}},
... false,true);
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })출력 결과에서 nModified : 1이 반환된 것으로 보아 업데이트가 성공적으로 완료되었음을 알 수 있습니다. 여기서 update() 메서드의 세 번째 인자 false는 upsert 비활성화, 네 번째 인자 true는 다중 문서 업데이트(multi) 설정을 의미합니다.
4. 업데이트 결과 확인
수정된 문서를 다시 조회해 보겠습니다.
> db.updateObjects.find().pretty();
업데이트 후의 출력 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c6d688b0c3d5054b766a769"),
"CustomerId" : 1,
"CustomerName" : "Larry",
"TotalItems" : 100,
"ItemDetails" : [
{
"NameOfItem" : "Item_1",
"Amount" : 450
},
{
"NameOfItem" : "Item_2",
"Amount" : 500
},
{
"NameOfItem" : "Item_3",
"Amount" : 330
}
]
}결과 분석
위 출력 결과를 보면, 기존에 200이었던 Item_3의 Amount 값이 130만큼 증가하여 330으로 변경된 것을 확인할 수 있습니다. 반면 Item_1(450)과 Item_2(500)는 그대로 유지되었습니다.
핵심은 ItemDetails.$.Amount처럼 위치 연산자 $를 사용하면, 쿼리 조건(ItemDetails.NameOfItem: "Item_3")과 일치하는 첫 번째 배열 요소만 선택적으로 업데이트된다는 점입니다. 이 패턴은 MongoDB에서 중첩된 배열 데이터를 다룰 때 가장 널리 사용되는 기법입니다.