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: 특정 필드로 결과를 집계하여 반환합니다.
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
목적: 특정 필드에 대해 집계를 수행하고, 결과를 그 필드의 값으로 정렬합니다.
주요 사용법: 특정 필드의 값을 기준으로 문서를 집계하고 정렬할 때 사용됩니다.
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는 성능에 영향을 미칠 수 있으므로 필요한 필드만 정렬하는 것이 좋습니다.
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
}