MongoDB에서 다른 배열 내부에 중첩된 배열로부터 특정 레코드를 삭제하려면 $pull 연산자를 사용해야 합니다. 이미 생성된 컬렉션을 수정하는 작업이므로 update() 메서드와 함께 사용합니다.
1. 샘플 컬렉션 생성하기
먼저 문서가 포함된 컬렉션을 생성해 보겠습니다.
> db.demo213.insertOne({
... "id": 101,
... "details1": [
... {
... "Name": "Chris",
... "details2": [
... {
... "StudentName": "David",
... "Subject": "MongoDB"
... },
... {
... "StudentName": "Mike",
... "Subject": "MySQL"
... }
... ]
... }
... ]
... });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e3e300c03d395bdc2134704")
}위 예제에서는 details1 배열 안에 details2라는 중첩 배열이 포함된 구조를 만들었습니다. 이처럼 배열이 여러 겹으로 중첩된 경우에도 $pull 연산자를 활용하면 원하는 레코드만 정확하게 제거할 수 있습니다.
2. find() 메서드로 문서 조회하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 확인할 수 있습니다.
> db.demo213.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5e3e300c03d395bdc2134704"),
"id" : 101,
"details1" : [
{
"Name" : "Chris",
"details2" : [
{
"StudentName" : "David",
"Subject" : "MongoDB"
},
{
"StudentName" : "Mike",
"Subject" : "MySQL"
}
]
}
]
}3. 중첩 배열에서 특정 레코드 삭제하기
이제 다른 배열(details1) 내부에 중첩된 배열(details2)에서 특정 레코드를 삭제하는 쿼리를 살펴보겠습니다. 위치 연산자($)와 $pull을 조합하여 사용합니다.
> db.demo213.update({"id": 101, "details1.Name": "Chris"},
... {
... "$pull": {"details1.$.details2" : { "Subject": "MySQL" }}
... }, multi=true
...)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })여기서 핵심은 쿼리 조건에 details1.Name: "Chris"를 포함시켜 대상 문서를 정확히 지정하고, details1.$ 위치 연산자를 통해 일치하는 배열 요소를 참조한다는 점입니다. 그런 다음 $pull로 Subject가 "MySQL"인 레코드를 제거합니다.
4. 삭제 결과 확인하기
다시 find() 메서드를 실행하여 변경된 결과를 확인해 보겠습니다.
> db.demo213.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5e3e300c03d395bdc2134704"),
"id" : 101,
"details1" : [
{
"Name" : "Chris",
"details2" : [
{
"StudentName" : "David",
"Subject" : "MongoDB"
}
]
}
]
}출력 결과를 보면 Subject가 "MySQL"인 Mike의 레코드가 성공적으로 삭제되고, David의 레코드만 남아 있는 것을 확인할 수 있습니다.
정리
중첩 배열에서 특정 요소를 삭제할 때는 다음 세 가지가 핵심입니다.
- $pull 연산자: 지정한 조건과 일치하는 배열 요소를 제거합니다.
- 위치 연산자($): 쿼리 조건과 일치하는 첫 번째 배열 요소를 참조합니다.
- 정확한 쿼리 조건: 상위 배열의 필드까지 조건에 포함해야 위치 연산자가 올바르게 동작합니다.
이 방법을 응용하면 두 단계 이상 깊이 중첩된 배열 구조에서도 원하는 데이터만 선택적으로 관리할 수 있습니다.