MongoDB에서 배열 형태로 저장된 하위 문서(sub-document)를 필터링하려면 집계 파이프라인(aggregate)을 사용하고, 그 안에서 $unwind 연산자를 활용하면 됩니다. $unwind는 배열의 각 요소를 개별 문서로 분리해 주기 때문에, 이후 $match 단계에서 원하는 조건으로 손쉽게 필터링할 수 있습니다.
1. 샘플 컬렉션 생성하기
먼저 예제에 사용할 컬렉션을 만들고 문서를 삽입해 보겠습니다.
> db.demo662.insertOne(
... {
... "details":[
... {
... Name:"Chris",
... Marks:35
... },
... {
... Name:"Bob",
... Marks:45
... },
... {
... Name:"David",
... Marks:30
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5ea1b2be24113ea5458c7d04")
}위 문서에는 세 명의 학생 정보가 담긴 details 배열이 포함되어 있습니다. 각 하위 문서는 이름(Name)과 점수(Marks) 필드를 가지고 있습니다.
2. find() 메서드로 전체 문서 조회하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 확인할 수 있습니다.
> db.demo662.find();
실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5ea1b2be24113ea5458c7d04"), "details" : [ { "Name" : "Chris", "Marks" : 35 }, { "Name" : "Bob", "Marks" : 45 }, { "Name" : "David", "Marks" : 30 } ] }3. $unwind와 $match로 하위 문서 필터링하기
이제 하위 문서를 필터링하는 핵심 쿼리를 살펴보겠습니다. 아래 쿼리는 먼저 $unwind로 details 배열을 개별 문서로 분리한 뒤, $match를 통해 점수(Marks)가 40보다 큰 하위 문서만 걸러냅니다.
> db.demo662.aggregate({$unwind:"$details"},{$match:{"details.Marks":{$gt:40}}})실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5ea1b2be24113ea5458c7d04"), "details" : { "Name" : "Bob", "Marks" : 45 } }정리
결과를 보면 점수가 40 초과인 조건을 만족하는 Bob의 하위 문서만 반환된 것을 확인할 수 있습니다. 이처럼 $unwind로 배열을 분해한 후 $match로 조건을 적용하는 방식은 MongoDB에서 중첩된 배열 데이터를 필터링할 때 가장 널리 사용되는 패턴입니다. 필요에 따라 $group, $project 등의 다른 집계 연산자와 조합하면 더욱 복잡한 데이터 가공도 가능합니다.