Mongodb aggregation pipeline how to limit a group push

aggregation-framework, grouping, limit, mongodb, mongodb-query

Solution

Suppose the bottom left coordinates and the upper right coordinates are respectively `[0, 0]` and `[100, 100]`. From MongoDB 3.2 you can use the `$slice` operator to return a subset of an array which is what you want.

db.collection.aggregate([
    { "$match": { 
        "loc": { 
            "$geoWithin":  { 
                "$box": [ 
                    [0, 0], 
                    [100, 100]
                ]
            }
        }}
    }},
    { "$group": { 
        "_id": "$name",
        "submitted": { "$max": "$submitted" }, 
        "preview": { "$first": "$preview" }
        "locs": { "$push": "$loc" }
    }}, 
    { "$project": { 
        "locs": { "$slice": [ "$locs", 5 ] },
        "preview": 1,
        "submitted": 1
    }},
    { "$limit": 10 }
])

Problem

I am not able to limit the amount of pushed elements in a group function with aggregation pipeline. Is this possible? Small example: Data: ``` [ { "submitted": date, "loc": { "lng": 13.739251, "lat": 51.049893 }, "name": "first", "preview": "my first" }, { "submitted": date, "loc": { "lng": 13.639241, "lat": 51.149883 }, "name": "second", "preview": "my second" }, { "submitted": date, "loc": { "lng": 13.715422, "lat": 51.056384 }, "name": "nearpoint2", "preview": "my nearpoint2" } ] ``` Here is my aggregation pipeline: ``` var pipeline = [ //I want to limit the data to a certain area { $match: { loc: { $geoWithin: { $box: [ [locBottomLeft.lng, locBottomLeft.lat], [locUpperRight.lng, locUpperRight.lat] ] } } }}, // I just want to get the latest entries { $sort: { submitted: -1 } }, // I group by name { $group: { _id: "$name", // get name submitted: { $max: "$submitted" }, // get the latest date locs: { $push: "$loc" }, // push every loc into an array THIS SHOULD BE LIMITED TO AN AMOUNT 5 or 10 preview: { $first: "$preview" } } }, // Limit the query to at least 10 entries. { $limit: 10 } ]; ``` How can I limit the `locs` array to `10` or any other size? I tried something with `$each` and `$slice` but that does not seem to work.

Original source