Aggregations
Aggregation operations in MongoDB process data records and return calculated results. They combine values from multiple documents and can perform different operations on this combined data to produce a single result.
With an aggregation, each step of the pipeline takes in a document/documents, and transforms the data by applying an operation, and then the next stage takes in the output of this stage to apply the next operation.
Basic Concepts
The Aggregation Framework in Spring Data MongoDB is built on three main components: Aggregation
,
AggregationDefinition
, and AggregationResults
.
Aggregation
- Definition: Represents a MongoDB aggregation operation and holds the instructions for the aggregation pipeline.
- Creation: Created using the
newAggregation(...)
method of the Aggregation class, which takes a list of aggregation operations. - Execution: Run using the aggregate method of the
MongoTemplate
, which takes the desired output class as a parameter.
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
Aggregation agg = newAggregation(
pipelineOp1(),
pipelineOp2(),
pipelineOpn()
);
AggregationResults<OutputType> results = mongoTemplate.aggregate(agg, "INPUT_COLLECTION_NAME", OutputType.class);
List<OutputType> mappedResult = results.getMappedResults();
Let's Look at an Example
The MatchOperation
in Spring Data MongoDB is used to filter documents in the aggregation pipeline. It is equivalent to the $match
stage in
MongoDB's aggregation framework. The MatchOperation
allows you to specify criteria to select documents that match specific conditions, similar
to the find query.
To create a MatchOperation
, you use the Criteria class to define the conditions.
Example
Assume you have a collection of sales data and you want to filter the documents where the storeLocation
is
"New York" and the customer.satisfaction
is greater than or equal to 4.
- Define the Criteria: Use the Criteria class to define the filtering conditions.
- Create the MatchOperation: Use the
Aggregation.match
method with the definedCriteria
. - Build the Aggregation: Combine the
MatchOperation
with other operations in the aggregation pipeline. - Execute the Aggregation: Use the
MongoTemplate
to execute the aggregation.
Here is a complete example of how to use MatchOperation
in Spring Data MongoDB:
package com.mongodb.quickstart.repositories;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Repository;
import com.mongodb.quickstart.models.Sale;
import com.mongodb.quickstart.dtos.SaleDTO;
import java.util.List;
@Repository
public class SalesCustomRepositoryImpl implements SalesCustomRepository {
@Autowired
private MongoTemplate mongoTemplate;
public List<SaleDTO> findSalesInNewYorkWithHighSatisfaction() {
// Step 1: Define the Criteria
Criteria criteria = Criteria.where("storeLocation").is("New York")
.and("customer.satisfaction").gte(4);
// Step 2: Create the MatchOperation
MatchOperation matchStage = Aggregation.match(criteria);
// Step 3: Build the Aggregation
Aggregation aggregation = Aggregation.newAggregation(matchStage);
// Step 4: Execute the Aggregation
AggregationResults<SaleDTO> results = mongoTemplate.aggregate(aggregation, "sales", SaleDTO.class);
return results.getMappedResults();
}
}
Breakdown of the Code
- Define the
Criteria
:Criteria criteria = Criteria.where("storeLocation").is("New York")
.and("customer.satisfaction").gte(4);- This defines a filter to select documents where storeLocation is "New York" and
customer.satisfaction
is greater than or equal to 4.
- This defines a filter to select documents where storeLocation is "New York" and
- Create the
MatchOperation
:MatchOperation matchStage = Aggregation.match(criteria);
- This creates a
MatchOperation
with the defined criteria.
- This creates a
- Build the Aggregation:
Aggregation aggregation = Aggregation.newAggregation(matchStage);
- This constructs an aggregation pipeline with only the
MatchOperation
. You can add more stages as needed.
- This constructs an aggregation pipeline with only the
- Execute the Aggregation:
AggregationResults<SaleDTO> results = mongoTemplate.aggregate(aggregation, "sales", SaleDTO.class);
- This executes the aggregation on the "sales" collection and maps the results to SaleDTO objects.
The MatchOperation
is a way to filter documents in an aggregation pipeline. By defining criteria with the Criteria
class
and using the Aggregation.match
method, you can filter documents based on conditions in Spring Data MongoDB.
A Couple More Options
group - GroupOperation
The GroupOperation
corresponds to MongoDB's $group
stage. It is used to group documents by a specified
key and perform operations on the grouped data to return a single result for each group.
GroupOperation groupOperation = Aggregation.group("field").sum("value").as("total");
- group("field"): Groups documents by the specified field.
- sum("value").as("total"): Computes the sum of the value field for each group and stores the result in a field named total.
project - ProjectionOperation
The ProjectionOperation
corresponds to MongoDB's $project
stage. It reshapes each document in the stream
by including, excluding, or adding new fields.
ProjectionOperation projectOperation = Aggregation.project("field1", "field2")
.andExpression("field1 + field2").as("newField");
- project("field1", "field2"): Includes field1 and field2 in the output documents.
- andExpression("field1 + field2").as("newField"): Adds a new field by combining field1 and field2.
unwind - UnwindOperation
The UnwindOperation
corresponds to MongoDB's $unwind
stage. It deconstructs an array field
from the input documents to output a document for each element of the array.
UnwindOperation unwindOperation = Aggregation.unwind("arrayField");
- unwind("arrayField"): The name of the array field to unwind. Each element of the array will be output as a separate document.
sort / sortByCount - SortOperation / SortByCountOperation
The SortOperation
corresponds to MongoDB's $sort
stage, which sorts input documents in the specified order.
The SortByCountOperation
is used for sorting by count.
SortOperation sortOperation = Aggregation.sort(Sort.by(Sort.Order.asc("field1"), Sort.Order.desc("field2")));
- sort(Sort.by(...)): Sorts documents by the specified fields.
- Sort.Order.asc("field1"): Sorts documents in ascending order by field1.
- Sort.Order.desc("field2"): Sorts documents in descending order by field2.
SortByCountOperation sortByCountOperation = Aggregation.sortByCount("field");
- sortByCount("field"): Groups documents by field and sorts by the count of each group.
Supported Aggregation Operations & Stages
The Spring Data MongoDB has support for the following Operations & Stages:
-
addFields - AddFieldsOperation
-
bucket / bucketAuto - BucketOperation / BucketAutoOperation
-
count - CountOperation
-
densify - DensifyOperation
-
facet - FacetOperation
-
geoNear - GeoNearOperation
-
graphLookup - GraphLookupOperation
-
group - GroupOperation
-
limit - LimitOperation
-
lookup - LookupOperation
-
match - MatchOperation
-
merge - MergeOperation
-
project - ProjectionOperation
-
redact - RedactOperation
-
replaceRoot - ReplaceRootOperation
-
sample - SampleOperation
-
set - SetOperation
-
setWindowFields - SetWindowFieldsOperation
-
skip - SkipOperation
-
sort / sortByCount - SortOperation / SortByCountOperation
-
unionWith - UnionWithOperation
-
unset - UnsetOperation
-
unwind - UnwindOperation