Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to combine results of two MongoDB aggregation pipeline queries and perform another aggregation query on the combined result without using $facet?

My first query returns the following result, after various aggregation pipeline stages:

{ 
    "group" : "A",
    "count" : 6, 
    "total" : 20
},
{
    "group" : "B",
    "count" : 2,
    "total" : 50
}

My second query returns the following result, after various aggregation pipeline stages:

{
    "group": "A",
    "count": 4,
    "total": 80
},
{
    "group": "C",
    "count": 12,
    "total": 60
}

Both the queries are performed on the same collection, but groups and transforms the data differently based on the pipeline stages.

Both of my queries use different $match conditions, have various pipeline stages including $facet,$unwind,$group,$project and operators like $map,$reduce,$zip,$subtract...

db.collection.aggregate([
{ $unwind...},
{ $match....},
{ $facet...},
...
])

When I use $facet to run my queries as parallel queries, it gives the following error (because I'm already using $facet in my existing queries) :

$facet is not allowed to be used within a $facet stage

Expected Output:

I need to find the average value for each of the group.

For that, I need to combine the results of both the queries and perform queries on the combined result.

My combined stage should look like this:

{ 
    "group" : "A",
    "count" : 10, 
    "total" : 100 
},
{
    "group" : "B",
    "count" : 2,
    "total" : 50
},
{
    "group": "C",
    "count": 12,
    "total": 60
}

Expected final result with average value for each group:

{
    "group" : "A",
     "avg" : 10 
},
{
    "group" : "B",
    "avg" : 25
},
{
    "group": "C",
    "avg": 5
}

Are there any operators available in MongoDB aggregation pipeline to achieve this without modifying my existing queries?

How to achieve this use case?

Thanks!

like image 807
Tiya Jose Avatar asked Sep 05 '25 16:09

Tiya Jose


1 Answers

You can run your queries separately using $facet and then use below transformation to $group combined results by group and calculate the average:

db.collection.aggregate([
    {
        $facet: {
            first: [ { $match: { "_": true } } ], // your first query
            second: [ { $match: { "_": false } } ], // your second query
        }
    },
    {
        $project: {
            all: {
                $concatArrays: [ "$first", "$second" ]
            }
        }
    },
    {
        $unwind: "$all"
    },
    {
        $group: {
            _id: "$all.group",
            count: { $sum: "$all.count" },
            total: { $sum: "$all.total" },
        }
    },
    {
        $project: {
            _id: 0,
            group: "$_id",
            count: 1,
            total: 1,
            avg: { $divide: [ "$total", "$count" ] }
        }
    }
])

Mongo Playground

Note: I'm using the _ character to indicate which query the document comes from. Obviously you don't need it and you can replace $facet queries with your own

like image 138
mickl Avatar answered Sep 07 '25 17:09

mickl