How to Perform Aggregation in MongoDB using Java

Introduction

When you query MongoDB for data, there may be times that you want to group your results and provide metrics such as total counts or averages. In these cases, you’ll want to use aggregation to accomplish the task. Fortunately, aggregating MongoDB documents in Java is a simple process, and the examples we provide will make it easy to get started. In this article, we’ll explain how to perform aggregation in MongoDB using Java.

Prerequisites

Before we get started with our examples, let’s take a quick look at the prerequisites for this task. The system requirements are minimal:

  • Both MongoDB and the MongoDB Java driver must be properly configured beforehand.

  • The latest Java JDK must be properly installed and configured beforehand.

  • The MongoDB service needs to be running before you can proceed.

NOTE: For the examples shown in this tutorial, we assume that the MongoDB version is 4.0 and the MongoDB Java Driver is 3.8.2.

The MongoDB Test Data

In order to follow along with the examples in this tutorial, it’s a good idea to create a small sample dataset containing the same documents used in the examples. Insert the documents shown below into the collection name of your choice. In this article, the collection will be called “foodCollection”:

IDFood NameCategory
5ce6068b3fd48a1ecf86a709tacosnack
5ce6068b3fd48a1ecf86a70aguacamoleappetizer
5ce6068b3fd48a1ecf86a70bpizzasnack
5ce6068b3fd48a1ecf86a70cchowder soupappetizer
5ce5424e5623d0458e941e4cApricot ChickenMain Dish

The MongoDB Version:

{ "_id" : ObjectId("5ce6068b3fd48a1ecf86a709"), "foodName" : "taco", "category" : "snack" }
{ "_id" : ObjectId("5ce6068b3fd48a1ecf86a70a"), "foodName" : "guacamole", "category" : "appetizer" }
{ "_id" : ObjectId("5ce6068b3fd48a1ecf86a70b"), "foodName" : "pizza", "category" : "snack" }
{ "_id" : ObjectId("5ce6068b3fd48a1ecf86a70c"), "foodName" : "chowder soup", "category" : "appetizer" }
{ "_id" : ObjectId("5ce6068b3fd48a1ecf86a70d"), "foodName" : "Apricot Chicken", "category" : "Main Dish" }
{ "_id" : ObjectId("5ce6068b3fd48a1ecf86a70e"), "foodName" : "Beef Stake", "category" : "Main Dish" }

Why Use Aggregation in MongoDB?

You might wonder what the purpose of aggregation is and when it’s best to use this functionality. Simply put, aggregation allows you to group your results, which can be valuable when generating reports or performing an audit. For example, imagine a collection called books. This collection would contain fields such as title, price and type. With aggregation, we could group our results by type, returning counts of how many books were of type hardcover, how many were of type paperback, and how many were ebook.

The MongoDB Connection Details

Now that we’ve made sure the prerequisites are in place and created our sample dataset, we can look at some Java code. We begin by using the following segment of code:

MongoClient mongo = MongoClients.create("mongodb://127.0.0.1:27017");
MongoDatabase db = mongo.getDatabase("foodDB");
MongoCollection<document> webHostColl = db.getCollection("foodCollection");

The code shown above establishes a connection to the MongoDB deployment, then accesses both the database (foodDB) and the specified collection (foodCollection).

Performing Aggregation of MongoDB Documents Using aggregate.match in Java

The next step is to start the MongoDB aggregation pipeline, which can be accomplished by simply calling an aggregate function against a MongoDB collection. The aggregation pipeline consists of multiple stages, with each stage transforming the data that’s moving through the pipeline.

The aggregation pipeline begins with the matching of documents, which is known as the $match stage:

MongoDatabase db = mongo.getDatabase("foodDB");
db.getCollection("foodCollection").aggregate(
Arrays.asList(
Aggregates.match(Filters.eq("category", "snack")),

)
).forEach((Block<document>) System.out::println);

Let’s discuss what’s happening in this code. You can see that the match() method is used to filter the query and only allows the documents that match the criteria to pass through. In this example, the criteria is that the value of the "category" field must be "snack".

The result that’s returned should look like the following:

Document{{_id=5ce6068b3fd48a1ecf86a709, foodName=taco, category=snack}}
Document{{_id=5ce6068b3fd48a1ecf86a70b, foodName=pizza, category=snack}}

Performing Aggregation of MongoDB Documents Using aggregate.project in Java

Another stage in the aggregation pipeline is the $project atage, which limits what particular fields will be displayed after the aggregation stage.

MongoDatabase db = mongo.getDatabase("foodDB");
db.getCollection("foodCollection").aggregate(
Arrays.asList(
Aggregates.project(
Projections.fields(
Projections.excludeId(),
Projections.include("foodName","category")
)
)
)
).forEach((Block<document>) System.out::println);

After executing this code, the result should look like the following:

Document{{foodName=taco, category=snack}}
Document{{foodName=guacamole, category=appetizer}}
Document{{foodName=pizza, category=snack}}
Document{{foodName=chowder soup, category=appetizer}}
Document{{foodName=Apricot Chicken, category=Main Dish}}
Document{{foodName=Beef Stake, category=Main Dish}}

Note that the _id field was not included in the results. This is because it was excluded from the aggregation using the Projections.excludeId() method.

Combining the Aggregation stages: $match and $project

So far we’ve seen examples that illustrate two specific stages of the aggregation pipeline: $match and $project. In the code displayed below, we’ll demonstrate how to combine these aggregation stages using Java:

MongoDatabase db = mongo.getDatabase("foodDB");
db.getCollection("foodCollection").aggregate(
Arrays.asList(
Aggregates.match(Filters.eq("category", "snack")),
Aggregates.project(
Projections.fields(
Projections.excludeId(),
Projections.include("foodName","category")
)
)
)
).forEach((Block<document>) System.out::println);

This code will display the MongoDB documents that match the given criteria, while selecting specific fields to display at the same time. In this case, the match criteria remained the same from our first example: the value of "category" needed to be "snack". Additionally, the specific fields being selected remained the same from our second example: the fields "foodName" and "category" were included, and _id was excluded.

The results returned from this code should look something like this:

Document{{foodName=taco, category=snack}}
Document{{foodName=pizza, category=snack}}

You can see that our aggregation was performed successfully in both the $match stage and the $project stage. The only results returned were those that matched the criteria specified in the code, and only the selected fields are shown.

Conclusion

When you want to query for results that match some specified criteria and then group your results, MongoDB aggregation is the ideal tool for the job. Understanding the MongoDB aggregation pipeline and its stages is key to performing successful aggregations in your Java code. With the explanations and instructions provided in this article, you’ll have no trouble aggregating MongoDB documents using Java.

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.