[MongoDB] Aggregation

SangDosa·2025년 3월 1일

DataBase

목록 보기
2/2

1. Aggregation의 기본 개념
Aggregation Framework는 MongoDB에서 데이터를 변형하고 집계할 수 있는 강력한 도구입니다. MongoDB의 Aggregation Pipeline을 사용하여 데이터를 처리할 수 있습니다. 이 파이프라인은 여러 단계의 변환 작업을 순차적으로 적용하여 최종 결과를 도출합니다.

1.1 Aggregation Pipeline
Aggregation은 여러 단계(Stage)로 이루어져 있으며, 각 단계는 데이터를 처리하고 변형하는 연산자입니다.
각 단계에서 데이터를 변형하거나 그룹화하고, 최종적으로 결과를 반환합니다.

1.2 Aggregation Stage
Aggregation Pipeline은 여러 단계로 구성됩니다. 각 단계에서 사용되는 주요 연산자는 다음과 같습니다:

$match: 데이터를 필터링합니다.

$project: 필드를 변환하거나, 제거하거나, 새 필드를 추가합니다.

$group: 데이터를 그룹화하고 집계합니다.

$sort: 데이터를 정렬합니다.

$limit: 결과의 개수를 제한합니다.

$skip: 결과에서 특정 개수를 건너뜁니다.

$unwind: 배열을 분해하여 각 원소를 개별 문서로 만듭니다.

$lookup: 다른 컬렉션과 조인을 수행합니다.

$addFields: 필드를 추가하거나 업데이트합니다.

$count: 결과의 개수를 세어 반환합니다.

$sortByCount: 특정 필드로 결과를 집계하여 반환합니다.
  1. 각 Aggregation Stage의 상세 설명
2.1 $match
목적: 데이터를 필터링하여 조건에 맞는 문서만 다음 단계로 전달합니다.
주요 사용법: 특정 필드가 특정 값인지, 또는 값의 범위가 일정 범위에 속하는지 등을 필터링할 때 사용됩니다.

2.2 $project
목적: 문서의 필드를 선택하거나, 제거하거나, 필드를 새로 생성할 수 있습니다.
주요 사용법: 필드를 포함하거나 제외하고, 필드를 변환하거나 이름을 바꿔서 출력할 때 사용됩니다.

2.3 $group
목적: 문서를 그룹화하고, 각 그룹에 대한 집계를 수행합니다.
주요 사용법: 특정 필드를 기준으로 그룹화하고, 그룹별 합계, 평균, 최소/최대 값 등을 구할 때 사용됩니다.

2.4 $sort
목적: 결과를 정렬합니다.
주요 사용법: 특정 필드를 기준으로 오름차순/내림차순 정렬을 합니다.

2.5 $limit
목적: 결과에서 반환할 문서의 개수를 제한합니다.
주요 사용법: 상위 N개의 결과를 추출할 때 사용됩니다.

2.6 $unwind
목적: 배열을 풀어서 배열 내의 각 요소를 개별 문서로 만듭니다.
주요 사용법: 배열 필드를 갖는 문서에서 각 배열 항목을 별도의 문서로 다루고 싶을 때 사용됩니다.

2.7 $lookup
목적: 다른 컬렉션과 조인합니다.
주요 사용법: 다른 컬렉션의 데이터를 결합하려고 할 때 사용됩니다.

2.8 $count
목적: 결과의 개수를 셉니다.
주요 사용법: 특정 조건을 만족하는 문서 수를 구할 때 사용됩니다.

2.9 $sortByCount
목적: 특정 필드에 대해 집계를 수행하고, 결과를 그 필드의 값으로 정렬합니다.
주요 사용법: 특정 필드의 값을 기준으로 문서를 집계하고 정렬할 때 사용됩니다.
  1. 예시와 Spring Data MongoDB 적용

3.1 $match 예시
목적: 특정 조건에 맞는 문서만 선택.

예시:

json

db.orders.aggregate([
  { $match: { status: "shipped" } }
])

Spring Data MongoDB 예시:

java

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.match(Criteria.where("status").is("shipped"))
);

List<Order> orders = mongoTemplate.aggregate(aggregation, "orders", Order.class).getMappedResults();

유의 사항:

match는 조건을 만족하는 데이터만 추출하므로 성능에 중요한 영향을 미칠 수 있습니다. 필요한 조건만 필터링하여 사용해야 합니다.

3.2 $project 예시
목적: 필드 선택, 필드 이름 변경 또는 새 필드 생성.

예시:

json

db.orders.aggregate([
  { $project: { orderId: 1, total: 1, status: 1, discountPrice: { $multiply: ["$price", 0.9] } } }
])

Spring Data MongoDB 예시:

java

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.project("orderId", "total", "status")
        .andExpression("price * 0.9").as("discountPrice")
);

List<Order> orders = mongoTemplate.aggregate(aggregation, "orders", Order.class).getMappedResults();

유의 사항:

project는 주로 필드를 선택하거나 새 필드를 생성하는 데 사용됩니다. 필드 이름을 변경할 때는 .as() 메서드를 사용해 새 이름을 지정합니다.

3.3 $group 예시
목적: 특정 필드를 기준으로 데이터를 그룹화하고 집계를 수행.

예시:

json

db.orders.aggregate([
  { $group: { _id: "$status", totalAmount: { $sum: "$amount" } } }
])

Spring Data MongoDB 예시:

java

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.group("status")
        .sum("amount").as("totalAmount")
);


List<GroupResult> result = mongoTemplate.aggregate(aggregation, "orders", GroupResult.class).getMappedResults();

유의 사항:

group은 그룹화하려는 필드를 기준으로 집계가 이루어집니다. 집계된 결과는 _id 필드에 저장되므로, project 단계에서 _id를 다른 이름으로 변경해야 할 수 있습니다.

3.4 $sort 예시
목적: 결과를 특정 필드를 기준으로 정렬.

예시:

json

db.orders.aggregate([
  { $sort: { totalAmount: -1 } }
])

Spring Data MongoDB 예시:

java

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.sort(Sort.by(Sort.Order.desc("totalAmount")))
);

List<Order> orders = mongoTemplate.aggregate(aggregation, "orders", Order.class).getMappedResults();

유의 사항:

sort는 성능에 영향을 미칠 수 있으므로 필요한 필드만 정렬하는 것이 좋습니다.

  1. 결과값 예시
    예시: $group을 이용해 상태별 총액을 구하는 집계 예시

json

db.orders.aggregate([
  { $group: { _id: "$status", totalAmount: { $sum: "$amount" } } },
  { $sort: { totalAmount: -1 } }
])

결과값:

json

[
  { "_id": "shipped", "totalAmount": 5000 },
  { "_id": "pending", "totalAmount": 3000 },
  { "_id": "delivered", "totalAmount": 1000 }
]

Spring Data MongoDB 예시 결과:

java

List<GroupResult> result = mongoTemplate.aggregate(aggregation, "orders", GroupResult.class).getMappedResults();

GroupResult 클래스:

java

public class GroupResult {
    private String id; // _id
    private double totalAmount;

    // getters and setters
}
  1. 유의사항
    성능 최적화: Aggregation 연산은 대규모 데이터셋에서 성능 저하를 일으킬 수 있습니다. match, limit, skip 등을 적절히 사용하여 쿼리 성능을 최적화해야 합니다.
    메모리 사용량: 복잡한 집계 연산은 메모리 사용량을 급격히 증가시킬 수 있습니다. Aggregation의 결과가 많을 경우 allowDiskUse(true)를 사용하여 디스크 기반 처리를 할 수 있습니다.
    인덱스 활용: match와 같은 필터링 단계는 가능한 한 인덱스를 활용하도록 설계해야 성능이 향상됩니다.
profile
조용한 개발자

0개의 댓글