Computer >> 컴퓨터 >  >> 프로그래밍 >> MongoDB

MongoDB 중첩 배열 문서에서 특정 필드만 추출하는 쿼리 방법 ($filter와 $project 활용)

MongoDB에서 중첩된 배열 문서 내부의 특정 필드만 가져오고 싶을 때는 집계 파이프라인의 $filter$project 연산자를 함께 사용하면 됩니다. 이 방법을 단계별로 살펴보겠습니다.

1. 샘플 컬렉션 생성

먼저 실습에 사용할 컬렉션과 문서를 생성합니다. 아래 예제는 details1 → details2 → details3로 이어지는 다층 구조의 중첩 배열을 포함하고 있습니다.

> db.demo342.insertOne({
...    "Id": "101",
...    "details1" : {
...       "details2" : [
...          {
...             "details3" : [
...                {
...                   "Name": "Mike",
...                   "CountryName" : "US"
...                },
...                {
...                   "Name": "David",
...                   "CountryName" : "AUS"
...                },
...                {
...                   "Name": "Bob",
...                   "CountryName" : "UK"
...                }
...             ]
...          }
...       ]
...    }
... });
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e53ef99f8647eb59e5620a9")
}

2. 전체 문서 확인하기

find() 메서드를 사용해 컬렉션의 모든 문서를 조회해 보겠습니다.

> db.demo342.find();

위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.

{ "_id" : ObjectId("5e53ef99f8647eb59e5620a9"), "Id" : "101", "details1" : { "details2" : [ { "details3" : [ { "Name" : "Mike", "CountryName" : "US" }, { "Name" : "David", "CountryName" : "AUS" }, { "Name" : "Bob", "CountryName" : "UK" } ] } ] } }

현재는 details3 배열 안의 모든 요소(Mike, David, Bob)가 함께 반환되는 것을 확인할 수 있습니다.

3. $filter와 $project로 특정 필드만 추출하기

이제 중첩 배열에서 조건에 맞는 특정 요소만 남기고 나머지는 제거하는 쿼리를 작성해 보겠습니다. 여기서는 Name이 "Bob"인 문서만 추출하는 것을 목표로 합니다.

핵심 로직은 다음과 같습니다.

  • $map: details2 배열의 각 요소를 순회하며 내부의 details3 배열을 처리합니다.
  • $filter (내부): details3 배열에서 Name이 "Bob"과 일치하는 요소만 남깁니다.
  • $filter (외부): details3가 빈 배열이 된 details2 요소는 제거하여 불필요한 빈 구조가 남지 않도록 합니다.
  • $project: 최종적으로 원하는 필드 구조만 출력합니다.
> db.demo342.aggregate([
...    { "$project": {
...       "details1": {
...          "details2": {
...             "$filter": {
...                "input": {
...                   "$map": {
...                      "input": "$details1.details2",
...                      "in": {
...                         "details3": {
...                            "$filter": {
...                               "input": "$$this.details3",
...                               "cond": { "$eq": ["$$this.Name", "Bob"] }
...                            }
...                         }
...                      }
...                   }
...                },
...                "cond": { "$ne": ["$$this.details3", []] }
...             }
...          }
...       }
...    }}
... ])

4. 실행 결과 확인

위 집계 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.

{ "_id" : ObjectId("5e53ef99f8647eb59e5620a9"), "details1" : { "details2" : [ { "details3" : [ { "Name" : "Bob", "CountryName" : "UK" } ] } ] } }

정리

이처럼 $project로 출력할 필드 구조를 정의하고, $map으로 배열을 순회한 뒤, $filter의 cond 조건으로 원하는 값만 걸러내면 중첩 배열 깊숙이 있는 특정 필드만 정확하게 추출할 수 있습니다. 외부 $filter에서 빈 배열([])을 제외하는 조건을 추가하면 조건에 맞지 않는 요소까지 깔끔하게 제거되어 더욱 효율적인 결과를 얻을 수 있습니다.