MongoDB 중첩 문서 업데이트란?
MongoDB에서는 하나의 문서 안에 배열과 객체가 여러 겹으로 중첩된 구조를 자주 사용합니다. 이렇게 깊이 들어간 중첩 문서(nested document)의 특정 필드만 수정하고 싶다면 $set 연산자와 점 표기법(dot notation)을 함께 사용하면 됩니다.
아래 예제를 통해 컬렉션 생성부터 중첩 필드 업데이트, 결과 확인까지 전체 과정을 단계별로 살펴보겠습니다.
1단계: 컬렉션 생성 및 문서 삽입
먼저 insertOne() 메서드를 사용하여 데모용 컬렉션에 문서를 생성합니다. 이 문서에는 details 배열 안에 학생 정보와 과목(subjects) 배열이 중첩되어 있습니다.
> db.demo315.insertOne({ _id :101,
... details: [
... {Name: 'Chris', subjects: [{id:1001, SubjectName:"MySQL"}]}
... ]
... }
...)
{ "acknowledged" : true, "insertedId" : 101 }2단계: find()로 문서 조회하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.
> db.demo315.find().pretty();
위 쿼리를 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
{
"_id" : 101,
"details" : [
{
"Name" : "Chris",
"subjects" : [
{
"id" : 1001,
"SubjectName" : "MySQL"
}
]
}
]
}3단계: $set으로 중첩 필드 업데이트하기
이제 핵심 단계입니다. 아래 쿼리처럼 $set 연산자에 점 표기법으로 경로를 지정하면, 배열의 특정 위치에 있는 중첩 필드 값만 정확히 수정할 수 있습니다.
여기서 details.0.subjects.1.id는 각각 details 배열의 0번째 요소 → subjects 배열의 1번째 요소 → id 필드를 의미합니다.
> db.demo315.update ({_id:101}, { '$set': {"details.0.subjects.1.id" :1004} })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })nModified : 1이 반환되면 한 개의 문서가 성공적으로 수정된 것입니다.
4단계: 업데이트 결과 확인하기
다시 find() 메서드로 문서를 조회해 변경 사항을 확인해 보겠습니다.
> db.demo315.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : 101,
"details" : [
{
"Name" : "Chris",
"subjects" : [
{
"id" : 1001,
"SubjectName" : "MySQL"
},
{
"id" : 1004
}
]
}
]
}참고: 최신 MongoDB 버전에서의 주의사항
위 예제에서 사용한 update() 메서드는 구버전 방식으로, 현재는 더 이상 권장되지 않습니다(deprecated). MongoDB 4.2 이상 버전에서는 용도에 맞게 updateOne(), updateMany(), 또는 replaceOne()을 사용하는 것이 좋습니다.
예를 들어 동일한 작업을 updateOne()으로 수행하면 다음과 같습니다.
> db.demo315.updateOne(
{ _id: 101 },
{ $set: { "details.0.subjects.1.id": 1004 } }
)
정리
MongoDB에서 중첩 문서를 업데이트할 때 기억해야 할 핵심은 다음과 같습니다.
- $set 연산자: 지정한 필드만 선택적으로 수정하며, 나머지 데이터는 그대로 유지됩니다.
- 점 표기법: 배경.인덱스.필드 형태로 경로를 지정해 배열 내부의 특정 요소에 접근합니다.
- 존재하지 않는 경로 지정 시: 해당 경로가 없으면 새로운 필드나 배열 요소가 자동으로 생성될 수 있으므로 인덱스 번호를 정확히 확인해야 합니다.
이 세 가지만 기억하면 복잡하게 중첩된 문서 구조에서도 원하는 데이터를 안전하고 정확하게 수정할 수 있습니다.