You can make use of a $facet
stage, combined with $sort
/$limit
stages:
// { "price": 123 }
// { "price": 165 }
// { "price": 98 }
// { "price": 34 }
db.collection.aggregate([
{ $facet: {
min: [{ $sort: { price: 1 } }, { $limit: 1 }],
max: [{ $sort: { price: -1 } }, { $limit: 1 }]
}},
{ $project: { min: { $first: "$min.price" }, max: { $first: "$max.price" } } }
])
// { "min" : 34, "max" : 165 }
The $facet
stage allows us to run multiple aggregation pipelines within a single stage on the same set of input documents. Each sub-pipeline has its own field in the output document where its result is stored as an array of documents.
Each field is thus produced by its own aggregation pipeline whose first stage $sort
s prices in a specified order, followed by a $limit
stage that'll only keep the first item (the smallest as defined by the chosen ordering).
The second part of the pipeline (the $set
stage) is just there to clean-up the $facet
output to the format you wished for.
Note that a $sort
followed by a $limit
stage is optimised by Mongo (see here). This allows the sort operation to only maintain the top n results (in our case only 1 element) as it progresses.
Also note that our $sort
stages will benefit from having an index on price
.