Skip to main content

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.

  1. Define the Criteria: Use the Criteria class to define the filtering conditions.
  2. Create the MatchOperation: Use the Aggregation.match method with the defined Criteria.
  3. Build the Aggregation: Combine the MatchOperation with other operations in the aggregation pipeline.
  4. 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

  1. 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.
  2. Create the MatchOperation:
    MatchOperation matchStage = Aggregation.match(criteria);
    • This creates a MatchOperation with the defined criteria.
  3. Build the Aggregation:
    Aggregation aggregation = Aggregation.newAggregation(matchStage);
    • This constructs an aggregation pipeline with only the MatchOperation. You can add more stages as needed.
  4. 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