MongoDB에서 여러 단계로 중첩된(embedded) 문서 배열을 필터링하려면 aggregate() 메서드를 사용하는 것이 가장 효과적입니다. 이 글에서는 3단계로 깊이 중첩된 배열 구조에서 특정 조건에 맞는 문서만 추출하는 방법을 단계별로 살펴보겠습니다.
1. 샘플 컬렉션 생성
먼저 실습에 사용할 컬렉션을 만들고 문서를 삽입합니다. 아래 예제는 details1 → details2 → details3로 이어지는 3단계 중첩 구조를 가진 문서 두 개를 생성합니다.
> db.demo736.insertOne(
... {
... "_id": "101",
... "details1": [
... {
... "details2": [
... {
... "details3": {
... "Name": "John"
... }
... }
... ]
... }
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : "101" }
> db.demo736.insertOne(
... {
... "_id": "102",
... "details1": [
... {
... "details2": [
... {
... "details3": {
... "Name": "Robert"
... }
... }
... ]
... }
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : "102" }
2. 저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.
> db.demo736.find();
실행 결과는 다음과 같습니다.
{ "_id" : "101", "details1" : [ { "details2" : [ { "details3" : { "Name" : "John" } } ] } ] }
{ "_id" : "102", "details1" : [ { "details2" : [ { "details3" : { "Name" : "Robert" } } ] } ] }
3. aggregate()로 중첩 배열 필터링하기
3단계로 중첩된 문서 배열을 필터링하려면 애그리게이션 파이프라인에서 $unwind와 $match, $project 스테이지를 조합해 사용합니다.
- $unwind: 배열을 개별 문서로 분해하여 각 요소를 독립적으로 처리할 수 있게 합니다. 중첩 배열이므로 각 레벨마다 한 번씩 적용합니다.
- $match: 분해된 문서 중 원하는 조건(여기서는 Name이 "Robert")에 일치하는 것만 걸러냅니다.
- $project: 최종 출력에서 필요한 필드만 선택합니다. 여기서는 _id를 제외하고 이름 정보만 반환합니다.
> db.demo736.aggregate([
... {
... "$unwind": "$details1"
... },
... {
... "$unwind": "$details1.details2"
... },
... {
... "$match": {
... "details1.details2.details3.Name": "Robert"
... }
... },
... {
... $project: {
... _id: 0,
... Name: "$details1.details2.details3",
... }
... }
... ])
4. 실행 결과
위 쿼리를 실행하면 조건에 일치하는 문서만 다음과 같이 출력됩니다.
{ "Name" : { "Name" : "Robert" } }
정리
MongoDB에서 깊게 중첩된 배열 구조를 다룰 때는 $unwind로 배열을 펼친 후 $match로 필터링하고, $project로 결과 형태를 다듬는 패턴이 표준적인 접근 방식입니다. 이 방법을 응용하면 어떤 깊이의 중첩 구조든 원하는 데이터를 정확하게 추출할 수 있습니다.