배열 내에서 특정 조건에 맞는 요소를 찾아 값을 추가하려면 MongoDB의 $push 연산자와 함께 $elemMatch, 그리고 위치 연산자($)를 활용하면 됩니다. 이 글에서는 실제 예제를 통해 단계별로 살펴보겠습니다.
1. 테스트용 컬렉션 생성
먼저 insertOne() 메서드를 사용해 예제 문서를 담은 컬렉션을 생성합니다.
> db.demo94.insertOne(
... {
... "Details" : [
... {
... "Name" : "Chris",
... "Subject" : []
... },
... {
... "Name" : "David",
... "Subject" : []
... },
... {
... "Name" : "Bob",
... "Subject" : []
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2d553bb8903cdd865577a9")
}위 문서에는 Details라는 배열이 있고, 그 안에 Name과 빈 Subject 배열을 가진 세 개의 객체(Chris, David, Bob)가 들어 있습니다.
2. 저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.
> db.demo94.find();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5e2d553bb8903cdd865577a9"), "Details" : [
{ "Name" : "Chris", "Subject" : [ ] },
{ "Name" : "David", "Subject" : [ ] }, { "Name" : "Bob", "Subject" : [ ] }
]
}3. 조건에 맞는 배열 요소 업데이트하기
이제 핵심 부분입니다. 아래 쿼리는 Details 배열 안에서 Name이 "David"인 요소를 찾아, 해당 요소의 Subject 배열에 새 과목을 추가합니다.
> db.demo94.updateOne(
... {
... "Details": { "$elemMatch": { "Name": "David"}}
... },
... {
... "$push": { "Details.$.Subject": { "Subject": "MongoDB" }}
... }
...);
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }쿼리의 동작 방식을 정리하면 다음과 같습니다.
- $elemMatch: Details 배열 내에서 지정한 조건(Name: "David")을 만족하는 첫 번째 요소를 매칭합니다.
- 위치 연산자($): $elemMatch로 매칭된 배열 요소의 위치를 참조하여, 해당 요소의 하위 필드만 정확히 대상으로 지정합니다.
- $push: 매칭된 요소의 Subject 배열 끝에 새 값({ "Subject": "MongoDB" })을 추가합니다.
4. 업데이트 결과 확인
다시 find() 메서드로 문서를 조회해 보겠습니다.
> db.demo94.find();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5e2d553bb8903cdd865577a9"), "Details" : [
{ "Name" : "Chris", "Subject" : [ ] },
{ "Name" : "David", "Subject" : [ { "Subject" : "MongoDB" } ] },
{ "Name" : "Bob", "Subject" : [ ] }
]
}출력 결과를 보면 David의 Subject 배열에만 { "Subject": "MongoDB" } 값이 추가된 것을 확인할 수 있습니다. Chris와 Bob의 데이터는 그대로 유지됩니다.
마무리
이처럼 $elemMatch로 원하는 배열 요소를 찾고, 위치 연산자($)로 해당 요소를 지정한 뒤 $push로 값을 추가하면, 배열 전체를 덮어쓰지 않고도 특정 조건에 맞는 요소만 안전하게 업데이트할 수 있습니다. 이 패턴은 중첩 배열 구조를 다루는 실무에서 매우 자주 사용되므로 꼭 익혀두시기 바랍니다.