MongoDB에서 중첩 배열(nested array) 내부에 있는 특정 필드의 값을 증가시키려면 위치 연산자($)를 사용해야 합니다. 위치 연산자는 쿼리 조건과 일치하는 배열 요소의 자리를 자동으로 식별해 주기 때문에, 배열 안의 여러 문서 중 원하는 항목만 정확하게 수정할 수 있습니다.
1. 테스트용 컬렉션 생성
먼저 예제로 사용할 컬렉션을 만들고 문서를 삽입하겠습니다. 아래 예제에서는 학생 정보와 프로젝트 상세 내역이 배열 형태로 저장된 구조를 사용합니다.
> db.incrementInNestedArrayDemo.insertOne(
... {
... "StudentId": 100,
... "ProjectDetails": [
... {
... "ProjectId": 567778888,
... "TeamSize": 4
... },
... {
... "ProjectId": 67888999,
... "TeamSize": 2
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5c9a6b7b15e86fd1496b38aa")
}문서가 정상적으로 삽입되었다면 acknowledged: true와 함께 생성된 ObjectId가 반환됩니다.
2. 저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다. 가독성을 높이기 위해 pretty() 메서드를 함께 사용합니다.
> db.incrementInNestedArrayDemo.find().pretty();
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{
"_id" : ObjectId("5c9a6b7b15e86fd1496b38aa"),
"StudentId" : 100,
"ProjectDetails" : [
{
"ProjectId" : 567778888,
"TeamSize" : 4
},
{
"ProjectId" : 67888999,
"TeamSize" : 2
}
]
}현재 두 번째 프로젝트(ProjectId: 67888999)의 팀 규모(TeamSize)는 2명입니다. 이 값을 1만큼 증가시켜 보겠습니다.
3. 위치 연산자($)로 중첩 배열 값 증가시키기
중첩 배열 내부의 값을 증가시키려면 update()> 메서드와 함께 $inc 연산자, 그리고 위치 연산자인 $를 조합하여 사용합니다. 쿼리 조건에 StudentId와 ProjectDetails.ProjectId를 지정하면, 일치하는 배열 요소의 위치를 $가 대신 참조합니다.
> db.incrementInNestedArrayDemo.update(
{ "StudentId" : 100, "ProjectDetails.ProjectId": 67888999 },
{ $inc: { "ProjectDetails.$.TeamSize": 1 } }
);
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })실행 결과에서 nModified: 1이 반환된 것을 보면, 하나의 문서가 성공적으로 수정되었음을 알 수 있습니다.
핵심 포인트: ProjectDetails.$.TeamSize에서 $는 쿼리 조건(ProjectId: 67888999)과 일치한 배열 요소의 인덱스를 의미합니다. 덕분에 첫 번째 프로젝트가 아닌, 정확히 해당 프로젝트의 TeamSize만 업데이트됩니다.
4. 업데이트 결과 검증하기
TeamSize 값이 실제로 1 증가했는지 다시 한번 조회해 확인해 보겠습니다.
> db.incrementInNestedArrayDemo.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c9a6b7b15e86fd1496b38aa"),
"StudentId" : 100,
"ProjectDetails" : [
{
"ProjectId" : 567778888,
"TeamSize" : 4
},
{
"ProjectId" : 67888999,
"TeamSize" : 3
}
]
}두 번째 프로젝트의 TeamSize가 기존의 2에서 3으로 1 증가한 것을 확인할 수 있습니다. 반면 첫 번째 프로젝트의 TeamSize는 그대로 4로 유지되었습니다.
정리
- 중첩 배열 내 특정 요소의 값을 수정할 때는 위치 연산자($)를 사용합니다.
- 값을 증가 또는 감소시킬 때는 $inc 연산자를 활용합니다. 음수를 지정하면 값을 감소시킬 수도 있습니다.
- 쿼리 조건이 배열 내 여러 요소와 일치하는 경우, 위치 연산자는 첫 번째로 일치하는 요소에만 적용됩니다.
- MongoDB 3.6 이상에서는
arrayFilters옵션이나updateOne()/updateMany()메서드를 활용하면 더욱 유연한 배열 업데이트가 가능합니다.