My documents looks like this.
{
"_id" : ObjectId("572c4bffd073dd581edae045"),
"name" : "What's New in PHP 7",
"description" : "PHP 7 is the first new major version number of PHP since 2004. This course shows what's new, and what's changed.",
"difficulty_level" : "Beginner",
"type" : "Normal",
"tagged_skills" : [
{
"_id" : "5714e894e09a0f7d804b2254",
"name" : "PHP"
}
],
"created_at" : 1462520831.649,
"updated_at" : 1468233074.243 }
Is it possible to get recent 5 documents and total count in a single query. I am using two queries for this requirement as given below.
db.course.find().sort({created_at:-1}).limit(5)
db.course.count()
My documents looks like this.
{
"_id" : ObjectId("572c4bffd073dd581edae045"),
"name" : "What's New in PHP 7",
"description" : "PHP 7 is the first new major version number of PHP since 2004. This course shows what's new, and what's changed.",
"difficulty_level" : "Beginner",
"type" : "Normal",
"tagged_skills" : [
{
"_id" : "5714e894e09a0f7d804b2254",
"name" : "PHP"
}
],
"created_at" : 1462520831.649,
"updated_at" : 1468233074.243 }
Is it possible to get recent 5 documents and total count in a single query. I am using two queries for this requirement as given below.
db.course.find().sort({created_at:-1}).limit(5)
db.course.count()
Share
Improve this question
asked Aug 4, 2016 at 10:54
jarry jaferyjarry jafery
1,0361 gold badge15 silver badges26 bronze badges
4 Answers
Reset to default 7This is a perfect job for the aggregation framework.
db.course.aggregate(
[
{ "$sort": { "created_at": -1 }},
{ "$group": {
"_id": null,
"docs": { "$push": "$$ROOT" },
"count": { "$sum": 1 }
}},
{ "$project": { "_id": 0, "count": 1, "docs": { "$slice": [ "$docs", 5 ] } }}
]
)
If your MongoDB server doesn't support $slice
then you need to use the ugly and inefficient approach.
db.course.aggregate(
[
{ "$sort": { "created_at": -1 }},
{ "$group": {
"_id": null,
"docs": { "$push": "$$ROOT" },
"count": { "$sum": 1 }
}},
{ "$unwind": "$docs" },
{ "$limit": 5 }
]
)
You can implement this easily with $facet
myCollection.aggregate([
{
$facet: {
count: [{ $count: "value" }],
data: [{ $sort: { _id: -1 } }, { $skip: skip }, { $limit: limit }]
}
},
{ $unwind: "$count" },
{ $set: { count: "$count.value" } }
])
the return result will be like:
[
{
"count": 234,
"data": [
// ...
]
}
]
@styvane I tested in person, this query is even less efficient than twice queries.
// get count
db.course.aggregate([{$match:{}}, {$count: "count"}]);
// get docs
db.course.aggregate(
[
{$match:{}},
{ "$sort": { "created_at": -1 }},
{"$skip": offset},
{"$limit": limit}
]
)
No, there is no other way. Two queries - one for count - one with limit.