Distinct Aggregation in MongoDB – An Easy Guide

Distinct Aggregation Featured Image

In today’s tutorial, I will cover distinct aggregation in MongoDB.

Our previous tutorial talked about the distinct() function in MongoDB. We learned that the function helped us return unique or distinct values into the mongo shell.

However, there was a slight drawback associated with it.

The distinct() method could only return the values of the given fields. In the guide, I talk about retrieving full records or complete documents that match our query using the distinct aggregation of MongoDB.

So, we will cover two ways of returning unique value documents based on our query today. One is using the distinct command and the other is using the $group aggregate operator.

This guide aims to throw light on providing examples to demonstrate both the steps so it becomes easier for readers to understand their usage.

So, let us get this quick guide started.

The Distinct Command Syntax

Let us take a look at the syntax of the distinct command in MongoDB.

{
  distinct: "collection",
  key: "field",
  query: query,
  readConcern: read concern document,
  collation: collation document,
  comment: any
}

Note:

If the value of the specified field is an array, distinct considers each element as a separate value.

For example, if a field has the value [20, [20], 20], distinct considers the values [20, [20], and 20 as distinct values.

Syntax for Distinct Aggregation Using the $group Operator

Below is the syntax for the distinct aggregation method which we will accomplish using the $group operator in MongoDB:

{
  $group:
    {
      _id: expression, // Group By Expression
      field1: { accumulator1 : expression1 },
      ...
    }
 }

Using the Distinct Aggregation in MongoDB

Let us get started by taking a look at a few examples for retrieving unique values by using different methods.

Below is the collection I would like to use in this tutorial today:

> db.drones.find().pretty()
{
        "_id" : ObjectId("61673f46b34f185eb7b2bf0c"),
        "utility" : [
                "Natural Resource Exploration",
                "Remote sensing",
                "Real estate and construction",
                "Recreation",
                "Delivery"
        ],
        "onSale" : false,
        "name" : "Nimbari Gryphon Medeta 65",
        "price" : 77500,
        "weight" : "77 kilograms",
        "additionalDetails" : {
                "material" : "carbon fiber",
                "moreUses" : [
                        "Precision Agriculture",
                        "Land Inspection",
                        "Water Inspection",
                        "Cinematography"
                ]
        }
}
{
        "_id" : ObjectId("61673f46b34f185eb7b2bf0d"),
        "utility" : [
                "Natural Resource Exploration",
                "Remote sensing",
                "Real estate and construction",
                "Recreation",
                "Delivery"
        ],
        "onSale" : false,
        "name" : "X-Strimmer Eye",
        "price" : 23500,
        "weight" : "24 kilograms",
        "additionalDetails" : {
                "material" : "glass fiber",
                "moreUses" : [
                        "Precision Agriculture",
                        "Cinematography"
                ]
        }
}
{
        "_id" : ObjectId("61673f46b34f185eb7b2bf0e"),
        "utility" : [
                "Natural Resource Exploration",
                "Remote sensing",
                "Real estate and construction",
                "Recreation",
                "Delivery"
        ],
        "onSale" : false,
        "name" : "Khai Balemosh Shefqa TRX",
        "price" : 120500,
        "weight" : "80 kilograms",
        "additionalDetails" : {
                "material" : "aluminum",
                "moreUses" : [
                        "Precision Agriculture",
                        "Land Inspection"
                ]
        }
}
{
        "_id" : ObjectId("61673f46b34f185eb7b2bf0f"),
        "utility" : [
                "Natural Resource Exploration",
                "Recreation",
                "Delivery"
        ],
        "onSale" : false,
        "name" : "Sifinist Croma AX",
        "price" : 99500,
        "weight" : "97 kilograms",
        "additionalDetails" : {
                "material" : "lithium",
                "moreUses" : [
                        "Precision Agriculture",
                        "Land Inspection",
                        "Water Inspection",
                        "Videography"
                ]
        }
}
{
        "_id" : ObjectId("61673f46b34f185eb7b2bf10"),
        "utility" : [
                "Remote sensing",
                "Real estate and construction",
                "Recreation"
        ],
        "onSale" : false,
        "name" : "Drovce Finnifield FR-7",
        "price" : 87600,
        "weight" : "13 kilograms",
        "additionalDetails" : {
                "material" : "polysterene",
                "moreUses" : [
                        "Precision Agriculture",
                        "Land Inspection",
                        "Water Inspection",
                        "Videography"
                ]
        }
}

Using the Distinct Command in MongoDB

In this example, I will use the distinct command in MongoDB to retrieve unique values.

> db.runCommand ( { distinct: "drones", key: "utility" } )
{
        "values" : [
                "Delivery",
                "Natural Resource Exploration",
                "Real estate and construction",
                "Recreation",
                "Remote sensing"
        ],
        "ok" : 1
}

I have rendered unique values for the utility field using the distinct command.

Using Distinct Aggregation on a Top-Level Field in MongoDB

In this example, I will use the $group operator which we also call the distinct aggregation method for rendering unique values in MongoDB.

We have here an example of a top-level field operand for the distinct aggregation operation:

> db.drones.aggregate( [ { $group : { _id : "$price" } } ] )
{ "_id" : 120500 }
{ "_id" : 99500 }
{ "_id" : 87600 }
{ "_id" : 77500 }
{ "_id" : 23500 }

Using Distinct Aggregation on an Embedded Field in MongoDB using $group

In this example, I will operate on an embedded field to render distinct values using the distinct aggregation in MongoDB.

> db.drones.aggregate( [ { $group : { _id : "$additionalDetails.material" } } ] )
{ "_id" : "lithium" }
{ "_id" : "polysterene" }
{ "_id" : "carbon fiber" }
{ "_id" : "aluminum" }
{ "_id" : "glass fiber" }

Conclusion

Learn to use the distinct aggregation to render unique or distinct values in MongoDB.

Noteworthy References

https://database.guide/3-ways-to-return-distinct-values-in-mongodb/

https://docs.mongodb.com/manual/reference/command/distinct/

https://docs.mongodb.com/manual/reference/operator/aggregation/group/

https://stackoverflow.com/questions/16368638/mongodb-distinct-aggregation