본문 바로가기

기타

[MongoDB] Aggregation

반응형

MongoDB 사용하여 쿼리를 하던 중에 쿼리 최적화를 위해서 관련있는 여러 컬렉션간의 조인에 대한 필요성이 발생했다. 그런데 MongoDB NoSQL 데이터베이스이기 때문에 RDB 다르게 테이블 개념이 아니고 FK 등을 통해 테이블 간의 관계가의되어 있지 않아서 어떻게 조인을 하는지 검색해보았다. 검색 중에 MongoDB 문서에서 Aggregation 대한 정보를 찾았고 오늘은 이에 대해서 정리해보려 한다.

1. Aggregation

Aggregation 은 여러 document 들을 연산하여 나온 결과물을 반환하는 연산이다. RDB 에서 조인을 통해 여러 테이블의 데이터를 합쳐서 반환하는 것처럼 aggregation 도 여러 document 의 값들을 조건에 맞게 묶어서 그룹화한 결과를 반환한다.

 

mongo db client 에서 aggregation 을 사용하는 방법은 두가지이다. 직접 pipeline 의 각 스테이지별 쿼리를 입력하여 실행하는 aggregation pipeline 과 이미 구현된 함수들을 사용하여 하나의 기능을 수행하도록 하는 single purpose aggregation methods 가 있다.

- Aggregation Pipelines

Aggregation pipeline document 를 처리하는 여러가지 스테이지로 구분되어 있다. 각 스테이지는 입력된 document 들에 대하여 필터링, 그룹화, 값들의 연산 등의 동작을 수행한다. 각 스테이지의 결과는 다음 스테이지의 입력값으로 넘어간다. aggregation pipeline 의 결과는 총합, 평균, 최대값, 최소값 등 document 들의 그룹화한 결과로 반환될 수 있다.

 

아래는 aggregation 을 사용한 코드 예제이다. 아래는 두개의 pipeline 을 가지고 있는데, 첫번째는 $match 스테이지로 size 가 medium 인 document 만 필터링한다. 두번째 스테이지는 $group 스테이지로 첫번째 스테이지에서 필터링된 document 들을 name 으로 묶고 quantity 의 총합을 totalQuantity 에 저장하여 반환한다.

 

db.orders.aggregate( [

   // Stage 1: Filter pizza order documents by pizza size
   {
      $match: { size: "medium" }
   },

   // Stage 2: Group remaining documents by pizza name and calculate total quantity
   {
      $group: { _id: "$name", totalQuantity: { $sum: "$quantity" } }
   }

] )

- Single Purpose Aggregation Methods

이 방식은 하나의 collection 에서 docuement 들을 aggregation 하기 위해서 사용하는 방법이다. 이 방식은 간단하지만 aggregation pipeline 에 비해 수행할 수 있는 기능이 한정적이다.

 

메서드들의 종류는 다양한다. 대표적으로 다음과 같은 메서드들이 있다.

 

db.collection.count() 해당 collection 이나 view 에 있는 docuement 들의 개수를 반환한다.
db.collection.distinct() 지정된 필드에 대해서 distinct 한 값을 가지고 있는 docuement 들을 반환한다.

2. Aggregation Pipeline Stages

Aggregation pipeline 은 다양한 스테이지 연산자들을 가진다. 그 중에서 대표적인 stage 들을 정리한다.

- $count

해당 스테이지의 결과 document 들의 개수를 반환한다.

pipeline 에서 사용될때 {$count: <string>}  의 형태로 사용되며 <string> 에는 $count 의 결과값을 할당할 필드의 이름을 입력한다. 이때 필드의 이름은 $ 로 시작하거나 . 을 포함해서는 안된다.

 

db.scores.aggregate(
  [
    {
      $match: {
        score: {
          $gt: 80
        }
      }
    },
    {
      $count: "passing_scores"
    }
  ]
)

 

위의 쿼리는 score 가 80 이상인 document 의 개수를 반환한다.

위 쿼리의 결과값은 아래와 같은 형식으로 passing_scores 필드에 count 값이 입력되어 반환된다.

 

{"passing_scores": 4 }

- $group

$group 스테이지는 group key 를 기준으로 document 들을 구분한다. 구분된 document 들은 각 고유한 group key 별로 하나의 document 로 출력된다.

 

db.sales.aggregate( [
  {
    $group: {
       _id: null,
       count: { $count: { } }
    }
  }
] )

 

$group 스테이지를 group key _id 에 입력되는 값을 사용하여 grouping 을 수행한다. 이때 _id null 을 입력하면 아래와 같은 전체 document 들에 대한 grouping 이 수행된다.

 

{'_id': null, 'count': 1000}

 

만약 null 이 아닌 document key 를 입력하면 아래와 같이 실제 key 를 기준으로 grouping 한 결과를 출력한다.

 

{'_id': 'A', 'count': 533}, {'_id': 'B', 'count': 467}

- $match

$match 스테이지에서는 입력된 조건을 통과하는 document 들을 결과로 반환하는 필터링을 수행한다.

 

db.articles.aggregate(
    [ { $match : { author : "dave" } } ]
)

 

위의 예제를 실행하면 document 들 중에서 author dave document 들만 결과로 반환한다.

- $lookup

$lookup 은 같은 database 에 저장된 collection 들에 대하여 left outer join 을 수행하는 스테이지이다. $lookup 스테이지는 join 된 컬렉션의 document 를 포함하는 새로운 배열 필드를 추가한 결과를 다음 스테이지로 넘긴다.

 

db.col.aggregate(
  [
    {$lookup: {
        from: "COLLECTION_NAME",
        localField: "FIELD_FROM_INPUT_DOCS",
        foreignField: "FIELD_FROM_JOINED_DOCS",
        as: "OUTPUT_ARRAY_FIELD"
      }
    }
  ]
)

 

$lookup 스테이지는 from 을 통해서 join document collection 을 입력받고 두 document join 할 키를 각각 localField foreignField 로 입력받는다. localField 는 이전 스테이지에서 input 으로 넘어온 docuement 들의 필드 키이고 foreignField 는 ㅓjoin 을 위해 from 에서 입력한 collection docuement 의 필드 키를 입력받는다. 이 두개의 키로 join 한 결과는 "as" 에서 정의한 필드 키에 저장되어 결과로 출력된다.

 

이 외에도 다양한 스테이지들이 존재하는데 이들은 다음 링크의 mongo db document 에서 확인할 수 있다.

 

- https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/

 

Aggregation Pipeline Stages — MongoDB Manual

Docs Home → MongoDB Manual In the db.collection.aggregate() method and db.aggregate() method, pipeline stages appear in an array. Documents pass through the stages in sequence.All except the $out, $merge, $geoNear, and $changeStream stages can appear mul

www.mongodb.com

 

 

[Reference]

 

db.collection.aggregate() — MongoDB Manual

Docs Home → MongoDB Manual db.collection.aggregate(pipeline, options)mongosh MethodThis page documents a mongosh method. This is not the documentation for database commands or language-specific drivers, such as Node.js.For the database command, see the a

www.mongodb.com

 

반응형

'기타' 카테고리의 다른 글

[FastAPI] BackgroundTasks  (0) 2023.05.26
[NGINX] NGINX 란?  (1) 2023.05.11
[Gradle] Gradle 사용법 - 설치, 초기화 및  (1) 2023.01.17
[Gradle] Gradle 이란?  (1) 2023.01.14
[기타] Sync - Async / Blocking - Non-Blocking  (0) 2022.04.05