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

MongoDB에서 중첩 배열 필터링 조건 설정하기 – $filter와 $cond 활용법

MongoDB의 aggregate()에서 조건에 따라 중첩 배열을 필터링하려면 $filter$cond 연산자를 사용할 수 있습니다. $filter는 지정된 조건을 만족하는 요소만 골라서 배열의 부분 집합을 반환하는 연산자입니다.

이 글에서는 실제 예제를 통해 문서 생성부터 중첩 배열 필터링까지 단계별로 살펴보겠습니다.

1. 샘플 컬렉션 생성하기

먼저 insertOne() 메서드를 사용해 중첩 배열 구조를 가진 문서를 포함한 컬렉션을 생성합니다.

> db.demo725.insertOne(
...     {
...        "details": {
...           "userMessages": [
...              {
...                 "Messages": [
...                    { "Message": "Hello" },
...                    { "Message": "How" },
...                    { "Message": "are" }
...                 ]
...              },
...              {
...                 "Messages": [
...                    { "Message": "Good" },
...                    { "Message": "Bye" }
...                 ]
...              },
...              {
...                 "Messages": [
...                    { "Message": "Hello" },
...                    { "Message": "Bye" }
...                 ]
...              }
...           ]
...        }
...     }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5eab16cd43417811278f5893")
}

2. 저장된 문서 확인하기

find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.

> db.demo725.find();

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

{ "_id" : ObjectId("5eab16cd43417811278f5893"), "details" : { "userMessages" : [ { "Messages" : [ { "Message" : "Hello" }, { "Message" : "How" }, { "Message" : "are" } ] }, { "Messages" : [ { "Message" : "Good" }, { "Message" : "Bye" } ] }, { "Messages" : [ { "Message" : "Hello" }, { "Message" : "Bye" } ] } ] } }

3. 중첩 배열 필터링 쿼리 작성하기

이제 핵심인 중첩 배열 필터링 쿼리입니다. 아래 쿼리는 $addFields, $filter, $map, $anyElementTrue, $indexOfBytes를 조합하여 각 userMessages 요소 중 내부 메시지 배열에 "Hello"가 포함된 것만 남깁니다.

> db.demo725.aggregate([
...    {
...       $addFields: {
...          "details.userMessages": {
...             $filter: {
...                input: "$details.userMessages",
...                as: "out",
...                cond: {
...                   $anyElementTrue: {
...                      $map: {
...                         input: "$$out.Messages",
...                         in: { $gte: [ { $indexOfBytes: [ "$$this.Message", "Hello" ] }, 0 ] }
...                      }
...                   }
...                }
...             }
...          }
...       }
...    }
... ]).pretty()

쿼리 동작 원리

  • $addFields: 기존 필드 details.userMessages를 새로 계산된 값으로 대체합니다.
  • $filter: 외부 배열 userMessages의 각 요소($$out)에 대해 조건을 평가합니다.
  • $map + $indexOfBytes: 내부 Messages 배열의 각 메시지에서 "Hello" 문자열의 위치를 찾습니다. 위치가 0 이상이면 해당 메시지에 "Hello"가 포함된 것입니다.
  • $anyElementTrue: 내부 메시지 중 하나라도 조건을 만족하면 해당 요소를 최종 결과에 유지합니다.

4. 필터링 결과 확인하기

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

{
    "_id" : ObjectId("5eab16cd43417811278f5893"),
    "details" : {
        "userMessages" : [
            {
                "Messages" : [
                    {
                        "Message" : "Hello"
                    },
                    {
                        "Message" : "How"
                    },
                    {
                        "Message" : "are"
                    }
                ]
            },
            {
                "Messages" : [
                    {
                        "Message" : "Hello"
                    },
                    {
                        "Message" : "Bye"
                    }
                ]
            }
        ]
    }
}

결과를 보면 원래 3개였던 userMessages 요소 중 "Good"과 "Bye"만 포함된 두 번째 요소가 제거된 것을 확인할 수 있습니다. 즉, 내부 메시지 배열에 "Hello"가 포함된 요소만 성공적으로 필터링되어 반환되었습니다.

마무리

이처럼 MongoDB에서는 $filter$cond(그리고 $map, $anyElementTrue 같은 보조 연산자)를 조합하면 복잡한 중첩 배열 구조도 원하는 조건에 따라 손쉽게 필터링할 수 있습니다. 특히 배열 안에 배열이 있는 형태의 데이터를 다룰 때 매우 유용한 패턴이므로 꼭 익혀두시기 바랍니다.