Limit the output of each bucket in `$bucketAuto` aggregation stage of MongoDB

Viewed 281

Consider a collection user with the following documents:

{"id": 1, "name": "John", "designation": "customer"}
{"id": 2, "name": "Alison", "designation": "manager"}
{"id": 3, "name": "Sam", "designation": "customer"}
{"id": 4, "name": "George", "designation": "salesperson"}
{"id": 5, "name": "Will", "designation": "salesperson"}
{"id": 6, "name": "Daffney", "designation": "customer"}
{"id": 7, "name": "Julie", "designation": "salesperson"}
{"id": 8, "name": "Elliot", "designation": "customer"}
{"id": 9, "name": "Bruno", "designation": "customer"}
{"id": 10, "name": "Omar", "designation": "customer"}
{"id": 11, "name": "Sid", "designation": "customer"}
{"id": 12, "name": "Nelson", "designation": "manager"}

In the following operation, input documents are grouped into three buckets according to the values in the designation field:

db.users.aggregate([
    {
        "$bucketAuto": {
            groupBy: "$designation",
            buckets: 5,
            output: {
                "count": { $sum: 1 },
                "users" : {
                    $push: {
                        "name": "$name"
                    },
                }
            }
        }
    }
])

Following are the results of this operation:

/* 1 */
{
    "_id" : {"min" : "customer", "max" : "manager"},
    "count" : 7.0,
    "users" : [ 
        {"name" : "John"}, 
        {"name" : "Sam"}, 
        {"name" : "Daffney"}, 
        {"name" : "Elliot"}, 
        {"name" : "Bruno"}, 
        {"name" : "Omar"}, 
        {"name" : "Sid"}
    ]
}

/* 2 */
{
    "_id" : {"min" : "manager", "max" : "salesperson"},
    "count" : 2.0,
    "users" : [ 
        {"name" : "Nelson"},
        {"name" : "Alison"}
    ]
}

/* 3 */
{
    "_id" : {"min" : "salesperson", "max" : "salesperson"},
    "count" : 3.0,
    "users" : [ 
        {"name" : "George"}, 
        {"name" : "Will"},
        {"name" : "Julie"}
    ]
}

What I wanted to do was limit the number of results in the "users" attribute of the resulting documents to 2, something like this:

/* 1 */
{
    "_id" : {"min" : "customer", "max" : "manager"},
    "count" : 2.0,
    "users" : [ 
        {"name" : "John"}, 
        {"name" : "Sam"}
    ]
}

/* 2 */
{
    "_id" : {"min" : "manager", "max" : "salesperson"},
    "count" : 2.0,
    "users" : [ 
        {"name" : "Nelson"},
        {"name" : "Alison"}
    ]
}

/* 3 */
{
    "_id" : {"min" : "salesperson", "max" : "salesperson"},
    "count" : 2.0,
    "users" : [ 
        {"name" : "George"}, 
        {"name" : "Will"}
    ]
}

Is there some way I can do that?

1 Answers

I am not sure it is possible with $bucketAuto, but you can try $slice to get limited elements from array and $size to get number of element in array,

  • add this stage after $bucketAuto stage,
  {
    $addFields: {
      users: { $slice: ["$users", 2] }
    }
  },
  {
    $addFields: {
      count: { $size: "$users" }
    }
  }

Playground

Related