MongoDB 데이터 그룹화

MongoDBBeginner
지금 연습하기

소개

이 랩에서는 MongoDB 에서 데이터 집계의 기본 사항을 배우게 됩니다. 문서를 그룹화하고, 그룹화된 데이터에 대한 계산을 수행한 다음, 결과를 필터링, 정렬 및 재구성하기 위해 집계 파이프라인을 사용하는 데 중점을 둘 것입니다. 이러한 작업은 MongoDB 에서 데이터 분석 및 보고에 필수적입니다. 이 랩이 끝나면 $group 연산자와 기타 주요 집계 단계를 사용하여 데이터에서 의미 있는 통찰력을 추출하는 데 익숙해질 것입니다.

필드별 문서 그룹화

데이터 집계의 첫 번째 단계는 종종 공통 필드를 기반으로 문서를 그룹화하는 것입니다. 이 단계에서는 MongoDB 셸에 연결하고, 새 데이터베이스와 컬렉션을 생성한 다음, $group 연산자를 사용하여 카테고리별로 문서를 그룹화합니다.

먼저 터미널에서 다음 명령을 실행하여 MongoDB 셸을 엽니다.

mongosh

셸에 들어가면 test> 프롬프트가 표시됩니다. salesdb라는 새 데이터베이스로 전환하고 샘플 제품 데이터를 삽입해 보겠습니다. MongoDB 는 데이터를 처음 삽입할 때 데이터베이스와 컬렉션을 자동으로 생성합니다.

다음 명령을 복사하여 mongosh 셸에 붙여넣습니다.

use salesdb
db.products.insertMany([
  { category: "Electronics", brand: "Apple", price: 1200 },
  { category: "Electronics", brand: "Samsung", price: 800 },
  { category: "Electronics", brand: "Sony", price: 950 },
  { category: "Apparel", brand: "Nike", price: 150 },
  { category: "Apparel", brand: "Adidas", price: 120 },
  { category: "Books", brand: "Penguin", price: 25 },
  { category: "Books", brand: "Penguin", price: 35 }
]);

이제 데이터가 있으므로 집계를 수행할 수 있습니다. 다음 명령은 category 필드별로 문서를 그룹화하고 $sum 누산기를 사용하여 각 카테고리의 총 가격을 계산합니다.

db.products.aggregate([
  {
    $group: {
      _id: "$category",
      totalPrice: { $sum: "$price" }
    }
  }
]);

예시 출력:

[
  { "_id": "Books", "totalPrice": 60 },
  { "_id": "Apparel", "totalPrice": 270 },
  { "_id": "Electronics", "totalPrice": 2950 }
]

집계 단계를 자세히 살펴보겠습니다.

  • db.products.aggregate([...]): 집계를 수행하는 데 사용되는 메서드입니다. 파이프라인을 형성하는 단계 배열을 받습니다.
  • $group: 입력 문서를 그룹화하는 단계 연산자입니다.
  • _id: "$category": 그룹화할 키를 지정하는 표현식입니다. 여기서는 category 필드의 값을 기준으로 그룹화합니다. $ 접두사는 필드 경로를 나타냅니다.
  • totalPrice: { $sum: "$price" }: 누산기입니다. totalPrice라는 새 필드를 출력 문서에 정의합니다. $sum 연산자는 그룹 내 모든 문서의 price 필드 합계를 계산합니다.

여러 누적기 사용

$group 단계는 여러 집계를 동시에 계산할 수 있습니다. 각 그룹 내에서 평균을 계산하고, 최소값 또는 최대값을 찾고, 항목 수를 셀 수 있습니다. 이 단계에서는 단일 $group 단계에서 여러 누산기를 사용하는 방법을 보여줍니다.

여전히 mongosh 셸에 있고 salesdb 데이터베이스를 사용하고 있어야 합니다.

각 카테고리에 대한 총 가격, 평균 가격 및 제품 수를 계산하는 더 복잡한 집계를 작성해 보겠습니다.

db.products.aggregate([
  {
    $group: {
      _id: "$category",
      totalPrice: { $sum: "$price" },
      averagePrice: { $avg: "$price" },
      productCount: { $sum: 1 }
    }
  }
]);

예시 출력:

[
  {
    "_id": "Books",
    "totalPrice": 60,
    "averagePrice": 30,
    "productCount": 2
  },
  {
    "_id": "Apparel",
    "totalPrice": 270,
    "averagePrice": 135,
    "productCount": 2
  },
  {
    "_id": "Electronics",
    "totalPrice": 2950,
    "averagePrice": 983.3333333333334,
    "productCount": 3
  }
]

사용된 새로운 누산기는 다음과 같습니다.

  • averagePrice: { $avg: "$price" }: $avg 연산자는 그룹 내 모든 문서의 price 필드 평균을 계산합니다.
  • productCount: { $sum: 1 }: 이는 그룹 내 문서를 세는 일반적인 방법입니다. 각 문서에 대해 합계에 1을 더하여 효과적으로 문서를 셉니다.

그룹화된 데이터 필터링

데이터를 그룹화한 후에는 계산된 값을 기반으로 그룹을 필터링해야 하는 경우가 많습니다. 예를 들어, 총 판매액이 특정 금액을 초과하는 카테고리만 보고 싶을 수 있습니다. $match 단계는 이 목적으로 사용됩니다. $group 단계 이후에 배치하여 그룹화된 문서를 필터링할 수 있습니다.

제품의 총 가격이 500 보다 큰 카테고리를 찾아보겠습니다.

db.products.aggregate([
  {
    $group: {
      _id: "$category",
      totalPrice: { $sum: "$price" }
    }
  },
  {
    $match: {
      totalPrice: { $gt: 500 }
    }
  }
]);

예시 출력:

[{ "_id": "Electronics", "totalPrice": 2950 }]

이 파이프라인에서는 다음과 같습니다.

  1. $group 단계는 먼저 각 카테고리에 대한 totalPrice를 계산합니다.
  2. $group 단계의 출력 문서는 $match 단계로 전달됩니다.
  3. $match 단계는 이러한 문서를 필터링하여 totalPrice 필드가 500 보다 큰 ($gt) 문서만 유지합니다.

이는 집계 파이프라인의 강력함을 보여주며, 한 단계의 출력이 다음 단계의 입력이 됩니다.

그룹화된 데이터 정렬

그룹화 및 필터링된 데이터가 있으면 마지막 단계는 종종 정렬하는 것입니다. $sort 단계는 하나 이상의 필드를 기준으로 문서를 오름차순 또는 내림차순으로 정렬할 수 있도록 합니다.

제품을 카테고리별로 그룹화하고 총 가격을 계산한 다음 결과를 totalPrice 기준으로 내림차순 (높은 가격에서 낮은 가격 순) 으로 정렬해 보겠습니다.

db.products.aggregate([
  {
    $group: {
      _id: "$category",
      totalPrice: { $sum: "$price" }
    }
  },
  {
    $sort: {
      totalPrice: -1
    }
  }
]);

예시 출력:

[
  { "_id": "Electronics", "totalPrice": 2950 },
  { "_id": "Apparel", "totalPrice": 270 },
  { "_id": "Books", "totalPrice": 60 }
]

$sort 단계는 정렬할 필드와 정렬 순서를 지정하는 문서를 받습니다.

  • totalPrice: -1: 이는 totalPrice 필드를 기준으로 문서를 정렬합니다. 값 -1은 내림차순을 지정합니다. 오름차순으로 정렬하려면 1을 사용합니다.

여러 필드로 정렬할 수도 있습니다. 예를 들어, $sort: { category: 1, totalPrice: -1 }은 먼저 카테고리 이름으로 알파벳순 정렬하고, 동일한 이름의 카테고리에 대해서는 총 가격 내림차순으로 정렬합니다.

$project 를 사용한 출력 재구성

때로는 $group 단계의 출력 형식이 필요한 것과 정확히 일치하지 않을 수 있습니다. 예를 들어, 그룹 키는 기본적으로 _id로 명명됩니다. $project 단계는 필드를 추가, 제거 또는 이름을 변경하여 출력 문서를 재구성할 수 있도록 합니다.

카테고리별로 그룹화하고, 총 가격으로 정렬한 다음, 카테고리에 대한 보다 설명적인 필드 이름을 갖도록 출력을 재구성하는 파이프라인을 구축해 보겠습니다.

db.products.aggregate([
  {
    $group: {
      _id: "$category",
      totalPrice: { $sum: "$price" }
    }
  },
  {
    $sort: {
      totalPrice: -1
    }
  },
  {
    $project: {
      _id: 0,
      category: "$_id",
      total: "$totalPrice"
    }
  }
]);

예시 출력:

[
  { "category": "Electronics", "total": 2950 },
  { "category": "Apparel", "total": 270 },
  { "category": "Books", "total": 60 }
]

$project 단계는 다음과 같이 작동합니다.

  • _id: 0: 이는 출력에서 _id 필드를 제외합니다. 기본적으로 _id는 명시적으로 제외되지 않는 한 항상 포함됩니다.
  • category: "$_id": 이는 category라는 새 필드를 생성하고 기존 _id 필드의 값을 할당합니다.
  • total: "$totalPrice": 이는 total이라는 새 필드를 생성하고 totalPrice 필드의 값을 할당합니다.

$project를 사용하는 것은 애플리케이션이나 보고서를 위해 집계 파이프라인의 최종 출력을 형식화하는 강력한 방법입니다.

요약

이 실습에서는 MongoDB 집계 파이프라인을 사용하여 데이터를 그룹화하고 분석하는 방법을 배웠습니다. $group 연산자를 사용하여 문서를 그룹화하고 합계를 계산하는 것부터 시작했습니다. 그런 다음 $avg$sum: 1과 같은 여러 누적기 (accumulator) 를 사용하여 더 복잡한 계산을 수행하도록 확장했습니다. 또한 집계 단계를 연결하는 방법을 배웠으며, $match를 사용하여 그룹화된 결과를 필터링하고, $sort를 사용하여 정렬하고, $project를 사용하여 최종 출력을 깔끔하고 읽기 쉬운 형식으로 재구성했습니다. 이러한 기술은 MongoDB 를 다루는 모든 개발자 또는 데이터 분석가에게 필수적인 기술입니다.