How can I sort a query by the number of elements of an array field?
Let say I have records like
{
title: '',
author: '',
votes: [id,id,id]
}
I would like to do sort by the length of the array votes
How can I sort a query by the number of elements of an array field?
Let say I have records like
{
title: '',
author: '',
votes: [id,id,id]
}
I would like to do sort by the length of the array votes
Use the aggregation framework with help from the $size
operator from MongoDB 2.6 and upwards:
db.collection.aggregate([
// Project with an array length
{ "$project": {
"title": 1,
"author": 1,
"votes": 1,
"length": { "$size": "$votes" }
}},
// Sort on the "length"
{ "$sort": { "length": -1 } },
// Project if you really want
{ "$project": {
"title": 1,
"author": 1,
"votes": 1,
}}
])
Simple enough.
If you do not have a version 2.6 available you can still do this with a little more work:
db.collection.aggregate([
// unwind the array
{ "$unwind": "$votes" },
// Group back
{ "$group": {
"_id": "$id",
"title": { "$first": "$title" },
"author": { "$first": "$author" },
"votes": { "$push": "$votes" },
"length": { "$sum": 1 }
}},
// Sort again
{ "$sort": { "length": -1 } },
// Project if you want to
{ "$project": {
"title": 1,
"author": 1,
"votes": 1,
}}
])
That is pretty much it.
With regular queries, you can only sort matched documents by field values. Aggregation queries will allow you to calculate the size of the array and sort by that values. Downside of using aggregation is that it can be slow.
If you're can't use aggregation, there is a workaround solution. You can create a field (e.g. voteCount
) where you will store the size of your votes
array. You can then create an index on that field and sort your documents by it. The upside of this approach is that the query will be fast. The downside of this approach is that you will manually have to keep count of the number of items in your array.
Try this:
db.collection.find().sort({votes:-1})
This will find all the posts and then sort the posts by the Votes. Here Votes is an array, so it will sort according to the array length in decreasing order (most liked on the top) because of the -1 inside sort({votes:-1}).