MongoDB에서 배열 필드 내부의 요소 중 특정 조건에 맞는 값만 추출하려면 $filter 연산자를 사용하면 됩니다. 이 글에서는 실제 예제를 통해 테스트용 문서를 생성하고, $filter를 활용해 원하는 데이터만 걸러내는 과정을 단계별로 살펴보겠습니다.
1. 샘플 컬렉션 생성
먼저 insertOne() 메서드로 테스트용 문서를 삽입합니다. 이 문서에는 세 사람의 정보가 담긴 details 배열이 포함되어 있습니다.
> db.demo751.insertOne(
... {
... _id: 101,
... details: [
... { Name: "Robert", id:110,Age:21},
... { Name: "Rae", id:110,Age:22},
... {Name: "Ralph", id:116,Age:23}
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : 101 }
2. 저장된 문서 확인
find() 메서드를 사용해 컬렉션의 전체 문서를 조회해 보겠습니다.
> db.demo751.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : 101,
"details" : [
{
"Name" : "Robert",
"id" : 110,
"Age" : 21
},
{
"Name" : "Rae",
"id" : 110,
"Age" : 22
},
{
"Name" : "Ralph",
"id" : 116,
"Age" : 23
}
]
}
3. $filter로 특정 값 필터링하기
이제 aggregate() 파이프라인에서 $addFields, $let, $filter를 조합하여 id가 110인 요소만 걸러낸 뒤, 그중 마지막 요소 하나만 잘라내는($slice) 쿼리를 작성해 보겠습니다.
> db.demo751.aggregate([
... {
... $addFields: {
... details: {
... $let: {
... vars: {
... filtered: { $filter: { input: "$details", as: "out", cond: { $eq: [ "$$out.id", 110 ] } } }
... },
... in: { $slice: [ "$$filtered", -1 ] }
... }
... }
... }
... }
... ])
쿼리 동작 방식
- $filter:
details배열을 순회하면서cond조건($$out.id == 110)을 만족하는 요소만 새 배열로 반환합니다. - $let: 필터링된 결과를 임시 변수
filtered에 담아 이후 단계에서 재사용할 수 있게 해줍니다. - $slice: 필터링된 배열에서 뒤에서 첫 번째(-1)에 해당하는 요소만 선택합니다.
- $addFields: 기존
details필드를 필터링된 결과로 덮어씁니다.
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : 101, "details" : [ { "Name" : "Rae", "id" : 110, "Age" : 22 } ] }
결과를 보면 id가 110인 두 개의 요소(Robert, Rae) 중 $slice 옵션에 의해 마지막 요소인 Rae의 정보만 최종적으로 반환된 것을 확인할 수 있습니다. 이처럼 $filter와 다른 집계 연산자를 조합하면 복잡한 배열 데이터도 원하는 형태로 손쉽게 가공할 수 있습니다.