MongoDB에서 findAndModify()로 배열 업데이트하기
MongoDB에서 문서 내부의 배열 요소를 조건에 맞게 수정하려면 일반적인 update 계열 메서드보다 findAndModify() 메서드를 사용하는 것이 효과적입니다. 이 메서드는 문서를 검색하고 수정하는 작업을 하나의 원자적(atomic) 연산으로 처리할 수 있어, 조회와 업데이트가 동시에 필요한 경우 특히 유용합니다.
이번 글에서는 실제 예제를 통해 findAndModify()를 사용해 배열 요소를 업데이트하는 과정을 단계별로 살펴보겠습니다.
1단계: 컬렉션 생성 및 문서 삽입
먼저 demo152라는 컬렉션을 만들고 두 개의 문서를 삽입합니다.
> db.demo152.insertOne({"id":102,"Name":["Chris","David"],Score:45});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e3515bcfdf09dd6d08539dd")
}
> db.demo152.insertOne({"id":103,"Name":["Mike","Carol"],Score:65});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e3515cafdf09dd6d08539de")
}2단계: 삽입된 문서 확인
find() 메서드를 사용해 컬렉션의 모든 문서를 조회합니다.
> db.demo152.find();
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5e3515bcfdf09dd6d08539dd"), "id" : 102, "Name" : [ "Chris", "David" ], "Score" : 45 }
{ "_id" : ObjectId("5e3515cafdf09dd6d08539de"), "id" : 103, "Name" : [ "Mike", "Carol" ], "Score" : 65 }3단계: findAndModify()로 배열 업데이트 실행
다음은 배열을 업데이트하는 핵심 쿼리입니다.
> var d = db.demo152.findAndModify({
... query: {
... id:102,
... Score: {$lt:50},
... Name: "Chris"
... },
... update: {
... $set : {"Name.$": "Robert"},
... $inc: {Score: 20 }
... }
... }
...
... )이 쿼리의 동작 방식을 살펴보면 다음과 같습니다.
- query 부분: id가 102이고, Score가 50 미만($lt:50)이며, Name 배열에 "Chris"가 포함된 문서를 찾습니다.
- $set과 위치 연산자($): "Name.$" 표기는 쿼리 조건과 일치한 배열 요소의 위치를 가리키는 위치 연산자입니다. 따라서 "Chris"가 있는 자리만 정확히 "Robert"로 교체됩니다.
- $inc 연산자: 해당 문서의 Score 값을 20만큼 증가시킵니다.
4단계: 업데이트 결과 확인
업데이트 후 다시 find() 메서드로 전체 문서를 조회합니다.
> db.demo152.find();
실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5e3515bcfdf09dd6d08539dd"), "id" : 102, "Name" : [ "Robert", "David" ], "Score" : 65 }
{ "_id" : ObjectId("5e3515cafdf09dd6d08539de"), "id" : 103, "Name" : [ "Mike", "Carol" ], "Score" : 65 }결과를 보면 id가 102인 문서에서 Name 배열의 "Chris"가 "Robert"로 변경되었고, Score도 45에서 65로 20 증가한 것을 확인할 수 있습니다. 반면 조건에 맞지 않는 id 103 문서는 그대로 유지되었습니다.
정리
MongoDB에서 배열의 특정 요소를 조건 기반으로 수정할 때는 findAndModify()와 위치 연산자($)를 함께 사용하면 됩니다. 이 방식은 검색 조건과 일치하는 배열 요소만 정확히 교체할 수 있으며, $inc, $set 등의 업데이트 연산자를 조합해 하나의 쿼리로 여러 필드를 동시에 처리할 수 있다는 장점이 있습니다.