MongoDB 문서에 저장된 이중 중첩 배열(doubly-nested array)에서 특정 요소를 제거하려면 $pull 연산자를 사용하면 됩니다. $pull은 지정한 조건과 일치하는 값을 배열에서 자동으로 삭제해 주는 업데이트 연산자로, 중첩된 배열 경로를 정확히 지정해 주면 깊숙이 위치한 요소도 손쉽게 제거할 수 있습니다.
1. 예제용 컬렉션 생성
개념을 이해하기 위해 먼저 샘플 문서가 포함된 컬렉션을 만들어 보겠습니다. 아래 쿼리는 사용자 정보(UserDetails) 안에 위치 정보(UserLocation)가 다시 중첩된 구조의 문서 두 개를 삽입합니다.
> db.removeElementFromDoublyNestedArrayDemo.insertOne(
... {
... "_id" : "1",
... "UserName" : "Larry",
... "UserDetails" : [
... {
... "UserCountryName" : "US",
... "UserLocation" : [
... {
... "UserCityName" : "New York"
... },
... {
... "UserZipCode" : "10001"
... }
... ]
... }
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : "1" }
> db.removeElementFromDoublyNestedArrayDemo.insertOne(
... {
... "_id" : "2",
... "UserName" : "Mike",
... "UserDetails" : [
... {
... "UserCountryName" : "UK",
... "UserLocation" : [
... {
... "UserCityName" : "Bangor"
... },
... {
... "UserZipCode" : "20010"
... }
... ]
... }
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : "2" }2. find()로 전체 문서 확인
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다.
> db.removeElementFromDoublyNestedArrayDemo.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : "1",
"UserName" : "Larry",
"UserDetails" : [
{
"UserCountryName" : "US",
"UserLocation" : [
{
"UserCityName" : "New York"
},
{
"UserZipCode" : "10001"
}
]
}
]
}
{
"_id" : "2",
"UserName" : "Mike",
"UserDetails" : [
{
"UserCountryName" : "UK",
"UserLocation" : [
{
"UserCityName" : "Bangor"
},
{
"UserZipCode" : "20010"
}
]
}
]
}3. $pull 연산자로 이중 중첩 배열의 요소 제거하기
이제 _id가 "2"인 문서의 UserDetails 배열 첫 번째 요소(인덱스 0) 내부에 있는 UserLocation 배열에서, UserZipCode 값이 "20010"인 항목을 제거해 보겠습니다.
> db.removeElementFromDoublyNestedArrayDemo.update(
... { _id : "2" },
... {$pull : {"UserDetails.0.UserLocation" : {"UserZipCode":"20010"}}}
... );
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })참고: 최신 MongoDB 버전에서는 update() 대신 updateOne() 또는 updateMany() 메서드 사용이 권장됩니다. 동작 방식은 동일합니다.
4. 변경 결과 확인
다시 find() 메서드를 실행하여 문서가 어떻게 변경되었는지 확인해 보겠습니다.
> db.removeElementFromDoublyNestedArrayDemo.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : "1",
"UserName" : "Larry",
"UserDetails" : [
{
"UserCountryName" : "US",
"UserLocation" : [
{
"UserCityName" : "New York"
},
{
"UserZipCode" : "10001"
}
]
}
]
}
{
"_id" : "2",
"UserName" : "Mike",
"UserDetails" : [
{
"UserCountryName" : "UK",
"UserLocation" : [
{
"UserCityName" : "Bangor"
}
]
}
]
}정리
출력 결과를 보면 Mike 문서의 UserLocation 배열에서 {"UserZipCode": "20010"} 항목이 사라진 것을 확인할 수 있습니다. 이처럼 $pull 연산자에 "UserDetails.0.UserLocation"과 같이 중첩 배열의 경로를 명시하고 제거할 조건을 함께 지정하면, 이중 중첩 배열 내부의 요소도 간단하게 삭제할 수 있습니다. 이제 해당 필드가 성공적으로 제거되었습니다.