MongoDB에서 하위 문서(subdocument) 내부의 배열을 조건에 맞게 필터링하려면 집계 파이프라인(aggregate)을 활용하는 것이 효과적입니다. 핵심 아이디어는 $unwind 연산자로 배열을 개별 문서로 펼친 후, $match로 원하는 조건을 걸고, 마지막에 $group으로 다시 묶어주는 것입니다.
1. 테스트용 컬렉션 생성하기
먼저 개념을 이해하기 위해 샘플 문서가 담긴 컬렉션을 생성해 보겠습니다. 아래 쿼리를 실행하면 배열 형태의 하위 문서를 포함한 컬렉션이 만들어집니다.
> db.filterArray.insertOne({ "L": [{ "N": 1 }, { "N": 2 }, { "N": 3 }, { "N": 4 }, { "N": 5 }] });쿼리 실행 후에는 다음과 같은 결과가 출력됩니다.
{
"acknowledged" : true,
"insertedId" : ObjectId("5c6d63f2734e98fc0a434aeb")
}2. 저장된 문서 확인하기
find() 메서드와 pretty()를 함께 사용하면 컬렉션에 저장된 문서를 보기 좋은 형태로 확인할 수 있습니다.
> db.filterArray.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c6d63f2734e98fc0a434aeb"),
"L" : [
{
"N" : 1
},
{
"N" : 2
},
{
"N" : 3
},
{
"N" : 4
},
{
"N" : 5
}
]
}3. 집계 파이프라인으로 배열 필터링하기
이제 실제로 하위 문서 배열을 필터링해 보겠습니다. 이 예제에서는 비교 연산자 $gt(greater than)를 사용하여 값이 3보다 큰 요소만 추출합니다.
전체 파이프라인의 동작 순서는 다음과 같습니다.
- $match: 특정
_id를 가진 문서만 먼저 선택합니다. - $unwind:
L배열을 각 요소별로 개별 문서로 분해합니다. - $match: 분해된 문서 중
L.N값이 3보다 큰 것만 걸러냅니다. - $group: 원래
_id기준으로 다시 그룹화하고,$push로 필터링된 값을 배열에 담습니다.
> db.filterArray.aggregate(
{ $match: { _id: ObjectId("5c6d63f2734e98fc0a434aeb") } },
{ $unwind: '$L' },
{ $match: { 'L.N': { $gt: 3 } } },
{ $group: { _id: '$_id', subDocument: { $push: '$L.N' } } }
).pretty();실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c6d63f2734e98fc0a434aeb"),
"subDocument" : [
4,
5
]
}정리
MongoDB에서 하위 문서 배열을 필터링할 때는 단순 find()만으로는 배열 전체가 반환되기 때문에, 위 예제처럼 $unwind → $match → $group 순서의 집계 파이프라인을 구성하는 것이 정석적인 접근 방식입니다. 이 패턴을 응용하면 $lt, $gte, $in 등 다양한 조건으로 배열 요소를 자유롭게 추출할 수 있습니다.