MongoDB Advanced Aggregations With Spring Boot and Amazon Corretto
Aasawari Sahasrabuddhe5 min read • Published Jun 26, 2024 • Updated Jun 26, 2024
FULL APPLICATION
Rate this tutorial
In this tutorial, we'll get into the understanding of aggregations and explore how to construct aggregation pipelines within your Spring Boot applications.
If you're new to Spring Boot, it's advisable to understand the fundamentals by acquainting yourself with the example template provided for performing Create, Read, Update, Delete (CRUD) operations with Spring Boot and MongoDB before delving into advanced aggregation concepts.
This tutorial serves as a complement to the example code template accessible in the GitHub repository. The code utilises sample data, which will be introduced later in the tutorial.
As indicated in the tutorial title, we'll compile the Java code using Amazon Corretto.
We recommend following the tutorial meticulously, progressing through each stage of the aggregation pipeline creation process.
Let's dive in!
This tutorial follows a few specifications mentioned below. Before you start practicing it, please make sure you have all the necessary downloads and uploads in your environment.
- A free Atlas tier, also known as an M0 cluster.
- Sample Data loaded in the cluster.
- Spring Data Version 4.2.2.
- MongoDB version 6.0.3.
- MongoDB Java Driver version 4.11.1.
Let’s understand each of these in detail.
Corretto comes with the ability to be a no-cost, multiplatform, production-ready open JDK. It also provides the ability to work across multiple distributions of Linux, Windows, and macOS.
You can read more about Amazon Corretto in Introduction to Amazon Corretto: A No-Cost Distribution of OpenJDK.
We will begin the tutorial with the first step of installing the Amazon Corretto 21 JDK and setting up your IDE with the correct JDK.
Step 1: Install Amazon Corretto 21 from the official website based on the operating system specifications.
Step 2: If you are on macOS, you will need to set the JAVA_HOME variable with the path for the Corretto. To do this, go to the system terminal and set the variable JAVA_HOME as:
1 export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-21.jdk/Contents/Home
Once the variable is set, you should check if the installation is done correctly using:
1 java --version 2 openjdk 21.0.2 2024-01-16 LTS 3 OpenJDK Runtime Environment Corretto-21.0.2.13.1 (build 21.0.2+13-LTS) 4 OpenJDK 64-Bit Server VM Corretto-21.0.2.13.1 (build 21.0.2+13-LTS, mixed mode, sharing)
For any other operating system, you will need to follow the steps mentioned in the official documentation from Java on how to set or change the PATH system variable and check if the version has been set.
Once the JDK is installed on the system, you can set up your IDE of choice to use Amazon Corretto to compile the code.
At this point, you have all the necessary environment components ready to kickstart your application.
In this part of the tutorial, we're going to explore how to write aggregation queries for a Spring Boot application.
Aggregations in MongoDB are like super-powered tools for doing complex calculations on your data and getting meaningful results back. They work by applying different operations to your data and then giving you the results in a structured way.
But before we get into the details, let's first understand what an aggregation pipeline is and how it operates in MongoDB.
Think of an aggregation pipeline as a series of steps or stages that MongoDB follows to process your data. Each stage in the pipeline performs a specific task, like filtering or grouping your data in a certain way. And just like a real pipeline, data flows through each stage, with the output of one stage becoming the input for the next. This allows you to build up complex operations step by step to get the results you need.
By now, you should have the sample data loaded in your Atlas cluster. In this tutorial, we will be using the
sample_supplies.sales
collection for our aggregation queries.The next step is cloning the repository from the link to test the aggregations. You can start by cloning the repository using the below command:
1 git clone https://github.com/mongodb-developer/spring-boot-mongodb-aggregations.git
Once the above step is complete, upon forking and cloning the repository to your local environment, it's essential to update the connection string in the designated placeholder within the
application.properties
file. This modification enables seamless connectivity to your cluster during project execution.After cloning the repository and changing the URI in the environment variables, you can try running the REST APIs in your Postman application.
All the extra information and commands you need to get this project going are in the README.md file which you can read on GitHub.
The Aggregation Framework support in Spring Data MongoDB is based on the following key abstractions:
- Aggregation
- AggregationDefinition
- AggregationResults
The Aggregation Framework support in Spring Data MongoDB is based on the following key abstractions: Aggregation, AggregationDefinition, and AggregationResults.
While writing the aggregation queries, the first step is to generate the pipelines to perform the computations using the operations supported.
The documentation on spring.io explains each step clearly and gives simple examples to help you understand.
For the tutorial, we have the REST APIs defined in the SalesController.java class, and the methods have been mentioned in the SalesRepository.java class.
The first aggregation makes use of a simple $match operation to find all the documents where the
storeLocation
has been specified as the match value.1 db.sales.aggregate([{ $match: { "storeLocation": "London"}}])
And now when we convert the aggregation to the spring boot function, it would look like this:
1 @Override 2 public List<SalesDTO> matchOp(String matchValue) { 3 MatchOperation matchStage = match(new Criteria("storeLocation").is(matchValue)); 4 Aggregation aggregation = newAggregation(matchStage); 5 AggregationResults<SalesDTO> results = mongoTemplate.aggregate(aggregation, "sales", SalesDTO.class); 6 return results.getMappedResults(); 7 }
In this Spring Boot method, we utilise the
MatchOperation
to filter documents based on the specified criteria, which in this case is the storeLocation
matching the provided value. The aggregation is then executed using the mongoTemplate
to aggregate data from the sales
collection into SalesDTO
objects, returning the mapped results.The REST API can be tested using the curl command in the terminal which shows all documents where
storeLocation
is London
.The next aggregation pipeline that we have defined with the rest API is to group all documents according to
storeLocation
and then calculate the total sales and the average satisfaction based on the matchValue
. This stage makes use of the GroupOperation
to perform the evaluation.1 @Override 2 public List<GroupDTO> groupOp(String matchValue) { 3 MatchOperation matchStage = match(new Criteria("storeLocation").is(matchValue)); 4 GroupOperation groupStage = group("storeLocation").count() 5 .as("totalSales") 6 .avg("customer.satisfaction") 7 .as("averageSatisfaction"); 8 ProjectionOperation projectStage = project("storeLocation", "totalSales", "averageSatisfaction"); 9 Aggregation aggregation = newAggregation(matchStage, groupStage, projectStage); 10 AggregationResults<GroupDTO> results = mongoTemplate.aggregate(aggregation, "sales", GroupDTO.class); 11 return results.getMappedResults(); 12 }
The REST API call would look like below:
1 curl http://localhost:8080/api/sales/aggregation/groupStage/Denver | jq
The next REST API is an extension that will streamline the above aggregation. In this case, we will be calculating the total sales for each store location. Therefore, you do not need to specify the store location and directly get the value for all the locations.
1 @Override 2 public List<TotalSalesDTO> TotalSales() { 3 GroupOperation groupStage = group("storeLocation").count().as("totalSales"); 4 SkipOperation skipStage = skip(0); 5 LimitOperation limitStage = limit(10); 6 Aggregation aggregation = newAggregation(groupStage, skipStage, limitStage); 7 AggregationResults<TotalSalesDTO> results = mongoTemplate.aggregate(aggregation, "sales", TotalSalesDTO.class); 8 return results.getMappedResults(); 9 }
And the REST API calls look like below:
1 curl http://localhost:8080/api/sales/aggregation/TotalSales | jq
1 @Override 2 public List<PopularDTO> findPopularItems() { 3 UnwindOperation unwindStage = unwind("items"); 4 GroupOperation groupStage = group("$items.name").sum("items.quantity").as("totalQuantity"); 5 SortOperation sortStage = sort(Sort.Direction.DESC, "totalQuantity"); 6 LimitOperation limitStage = limit(5); 7 Aggregation aggregation = newAggregation(unwindStage,groupStage, sortStage, limitStage); 8 return mongoTemplate.aggregate(aggregation, "sales", PopularDTO.class).getMappedResults(); 9 }
1 curl http://localhost:8080/api/sales/aggregation/PopularItem | jq
The last API mentioned makes use of the $bucket to create buckets and then calculates the count and total amount spent within each bucket.
1 @Override 2 public List<BucketsDTO> findTotalSpend(){ 3 ProjectionOperation projectStage = project() 4 .and(ArrayOperators.Size.lengthOfArray("items")).as("numItems") 5 .and(ArithmeticOperators.Multiply.valueOf("price") 6 .multiplyBy("quantity")).as("totalAmount"); 7 8 BucketOperation bucketStage = bucket("numItems") 9 .withBoundaries(0, 3, 6, 9) 10 .withDefaultBucket("Other") 11 .andOutputCount().as("count") 12 .andOutput("totalAmount").sum().as("totalAmount"); 13 14 Aggregation aggregation = newAggregation(projectStage, bucketStage); 15 return mongoTemplate.aggregate(aggregation, "sales", BucketsDTO.class).getMappedResults(); 16 }
1 curl http://localhost:8080/api/sales/aggregation/buckets | jq
This tutorial provides a comprehensive overview of aggregations in MongoDB and how to implement them in a Spring Boot application. We have learned about the significance of aggregation queries for performing complex calculations on data sets, leveraging MongoDB's aggregation pipeline to streamline this process effectively.
As you continue to experiment and apply these concepts in your applications, feel free to reach out on our MongoDB community forums. Remember to explore further resources in the MongoDB Developer Center and documentation to deepen your understanding and refine your skills in working with MongoDB aggregations.
Top Comments in Forums
There are no comments on this article yet.