Similar to SQL’s Group by analysis, MongoDB also supports it. This chapter introduces how to implement statistical analysis of MongoDB data using Golang.

Prerequisite Tutorial

Please read the prerequisite tutorial below:

Test Data

The data in the orders collection is as follows:

{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 }
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 }
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 }
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 }
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }

Grouping and Aggregation

Perform statistical queries using the Collection.Aggregate function.

Below is an example of statistical analysis in MongoDB:

[
    { $match: { status: "A" } },  // The first stage, matching document data based on query criteria
    { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },   // The second stage, grouping and aggregation
    { $sort: { total: -1 } }  // The third stage, sorting the results
]

Equivalent SQL:

select sum(amount) as total from orders 
        where status="A" 
        group by cust_id 
        order by total desc

Here’s how to achieve the same in Golang:

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    var coll *mongo.Collection

    // The code for connecting to MongoDB and obtaining collection objects is omitted here and can be referred to in the quick start tutorial.

    // Statistical analysis expression, using Golang data structure to represent the MongoDB native syntax.
    // If you are not familiar with the Golang MongoDB data model, please refer to the previous sections.
    pipeline := mongo.Pipeline{
            {{"$match", bson.D{{"status", "A"}}}},
            {{"$group", bson.D{{"_id", "$cust_id"}, {"total", bson.D{{"$sum", "$amount"}}}}}},
            {{"$sort", bson.D{{"total", -1}}}
    }

    // Set timeout
    opts := options.Aggregate().SetMaxTime(2 * time.Second)

    // Perform statistical analysis
    cursor, err := coll.Aggregate(
                                context.TODO(),  // Context parameter
                                pipeline,  // Statistical analysis expression
                                opts // Optional parameters
                            )
    if err != nil {
        log.Fatal(err)
    }

    // Define the result set, using the bson.M type (a type of map structure) to store the query results
    var results []bson.M
    // Get all results and store them in the results variable
    if err = cursor.All(context.TODO(), &results); err != nil {
        log.Fatal(err)
    }

    // Iterate through the query results
    for _, result := range results {
        fmt.Printf("id =  %v , total =  %v \n", result["_id"], result["total"])
    }
}

Tip: For more MongoDB aggregation syntax, please refer to MongoDB Aggregation Pipeline