For AI agents: a documentation index is available at https://www.mongodb.com/docs/llms.txt — markdown versions of all pages are available by appending .md to any URL path.

Group and Total Data

This tutorial illustrates how to construct an aggregation pipeline, perform the aggregation on a collection, and display the results using the language of your choice.

This tutorial demonstrates how to group and analyze customer order data. The results show the list of customers who purchased items in 2020 and include each customer's order history for 2020.

The aggregation pipeline performs the following operations:
This tutorial demonstrates how to group and analyze customer order data. The results show the list of customers who purchased items in 2020 and include each customer's order history for 2020, sorted by purchase date.
  • Matches a subset of documents by a field value

  • Groups documents by common field values

  • Adds computed fields to each result document


➤ Use the Select your language drop-down menu in the upper-right to set the language of the following examples or select MongoDB Shell.


This example uses an orders collection, which contains documents describing individual product orders. Because each order corresponds to only one customer, the aggregation groups order documents by the customer_id field, which contains customer email addresses.

To create the orders collection, use the insertMany() method:

db.orders.insertMany( [ { customer_id: "elise_smith@myemail.com", orderdate: new Date("2020-05-30T08:35:52Z"), value: 231, }, { customer_id: "elise_smith@myemail.com", orderdate: new Date("2020-01-13T09:32:07Z"), value: 99, }, { customer_id: "oranieri@warmmail.com", orderdate: new Date("2020-01-01T08:25:37Z"), value: 63, }, { customer_id: "tj@wheresmyemail.com", orderdate: new Date("2019-05-28T19:13:32Z"), value: 2, }, { customer_id: "tj@wheresmyemail.com", orderdate: new Date("2020-11-23T22:56:53Z"), value: 187, }, { customer_id: "tj@wheresmyemail.com", orderdate: new Date("2020-08-18T23:04:48Z"), value: 4, }, { customer_id: "elise_smith@myemail.com", orderdate: new Date("2020-12-26T08:55:46Z"), value: 4, }, { customer_id: "tj@wheresmyemail.com", orderdate: new Date("2021-02-29T07:49:32Z"), value: 1024, }, { customer_id: "elise_smith@myemail.com", orderdate: new Date("2020-10-03T13:49:44Z"), value: 102, }] )

The following steps demonstrate how to create and run an aggregation pipeline to group documents and compute new fields.

1

First, add a $match stage to the pipeline array you pass to aggregate(). The orders collection also contains orders from other years, and this stage excludes them from the rest of the pipeline:

{ $match: { orderdate: { $gte: new Date("2020-01-01T00:00:00Z"), $lt: new Date("2021-01-01T00:00:00Z"), }} },
2

Next, add a $sort stage to set an ascending sort on the orderdate field:

{ $sort: { orderdate: 1 } },
3

Add a $group stage to group orders by the value of the customer_id field. The _id field holds the grouping key, so each result document represents one customer.

In this stage, add accumulators that create the following fields in the result documents:

  • first_purchase_date: the date of the customer's first 2020 purchase. The $first accumulator returns the value from the first document in each group, and the preceding $sort stage on orderdate makes that the customer's earliest order

  • total_value: the total value of all the customer's purchases, computed by $sum

  • total_orders: the total number of the customer's purchases, computed by adding 1 to a $sum accumulator for each order in the group

  • orders: the list of all the customer's purchases. The $push accumulator appends one entry to this array for each order in the group, which preserves the date and value of every individual order alongside the totals

{ $group: { _id: "$customer_id", first_purchase_date: { $first: "$orderdate" }, total_value: { $sum: "$value" }, total_orders: { $sum: 1 }, orders: { $push: { orderdate: "$orderdate", value: "$value" } }} },
4

Next, add another $sort stage to set an ascending sort on the first_purchase_date field. This stage orders the results so that the customers who ordered earliest in 2020 appear first:

{ $sort: { first_purchase_date: 1 } },
5

Add a $set stage to recreate the customer_id field from the _id field set by the $group stage:

{ $set: { customer_id: "$_id" } },
6

Finally, add an $unset stage. The $unset stage removes the _id field from the result documents, because the $set stage in the preceding step already copied its value to customer_id:

{ $unset: ["_id"] }
7

Run the completed pipeline on the orders collection:

db.orders.aggregate( [ // Stage 1: Match orders in 2020 { $match: { orderdate: { $gte: new Date("2020-01-01T00:00:00Z"), $lt: new Date("2021-01-01T00:00:00Z"), } } }, // Stage 2: Sort orders by date { $sort: { orderdate: 1 } }, // Stage 3: Group orders by email address (customer_id) { $group: { _id: "$customer_id", first_purchase_date: { $first: "$orderdate" }, total_value: { $sum: "$value" }, total_orders: { $sum: 1 }, orders: { $push: { orderdate: "$orderdate", value: "$value" } } } }, // Stage 4: Sort orders by first order date { $sort: { first_purchase_date: 1 } }, // Stage 5: Display the customers' email addresses { $set: { customer_id: "$_id" } }, // Stage 6: Remove unneeded fields { $unset: ["_id"] }] )
8

The aggregation returns the following summary of customers' orders from 2020. The result documents contain details on all orders placed by a given customer, grouped by the customer's email address and sorted by purchase date:

{ first_purchase_date: ISODate("2020-01-01T08:25:37.000Z"), total_value: 63, total_orders: 1, orders: [ { orderdate: ISODate("2020-01-01T08:25:37.000Z"), value: 63 } ], customer_id: 'oranieri@warmmail.com'}{ first_purchase_date: ISODate("2020-01-13T09:32:07.000Z"), total_value: 436, total_orders: 4, orders: [ { orderdate: ISODate("2020-01-13T09:32:07.000Z"), value: 99 }, { orderdate: ISODate("2020-05-30T08:35:52.000Z"), value: 231 }, { orderdate: ISODate("2020-10-03T13:49:44.000Z"), value: 102 }, { orderdate: ISODate("2020-12-26T08:55:46.000Z"), value: 4 } ], customer_id: 'elise_smith@myemail.com'}{ first_purchase_date: ISODate("2020-08-18T23:04:48.000Z"), total_value: 191, total_orders: 2, orders: [ { orderdate: ISODate("2020-08-18T23:04:48.000Z"), value: 4 }, { orderdate: ISODate("2020-11-23T22:56:53.000Z"), value: 187 } ], customer_id: 'tj@wheresmyemail.com'}
Select your language
Rate this page