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 $sorts 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.