Reputation: 281
I'm looking for a way to sort a nested array of objects.
Here's an example:
{
answers : [
{ name : 'paul', state : 'RU' },
{ name : 'steve', state : 'US' },
{ name : 'mike', state : 'DE' },
...
]
}
Suppose now I want to find all the name
, of the answers
array, but how can I sort them in ascending order?
Upvotes: 28
Views: 41636
Reputation: 16033
Since mongodb version 5.2, you can use $sortArray
:
db.engineers.aggregate([
{$set:
{answers: {$sortArray: {input: "$answers ", sortBy: { name: 1 } }}}
}
])
Upvotes: 3
Reputation: 1
I have found one solution for this while updating the nested array we can also sort that, after updating we will have an sorted array then we don't need to sort on find
db.students.update(
{ _id: 1 },
{
$push: {
quizzes: {
$each: [ `enter code here`{ id: 3, score: 8 }, { id: 4, score: 7 }, { id: 5, score: 6 } ],
$sort: { score: 1 }
}
}
}
)
Upvotes: -1
Reputation: 61666
Starting in Mongo 4.4
, the $function
aggregation operator allows applying a custom javascript function to implement behaviour not supported by the MongoDB Query Language.
For instance, in order to sort an array of objects by one of their fields:
// {
// "answers" : [
// { "name" : "steve", "state" : "US" },
// { "name" : "xavier", "state" : "FR" },
// { "name" : "paul", "state" : "RU" }
// ]
// }
db.collection.aggregate(
{ $set:
{ "answers":
{ $function: {
body: function(answers) { return answers.sort((a, b) => a.name > b.name); },
args: ["$answers"],
lang: "js"
}}
}
}
)
// {
// "answers" : [
// { "name" : "paul", "state" : "RU" },
// { "name" : "steve", "state" : "US" },
// { "name" : "xavier", "state" : "FR" }
// ]
// }
This modifies the array in place, without having to apply a combination of expensive $unwind
, $sort
and $group
stages.
$function
takes 3 parameters:
body
, which is the function to apply, whose parameter is the array to modify.args
, which contains the fields from the record that the body
function takes as parameter. In our case "$answers"
.lang
, which is the language in which the body
function is written. Only js
is currently available.Upvotes: 4
Reputation: 33145
I would store it in the order you want it back out. Or sort it after you pull it out, on the client side.
If neither of those are possible, you can use the aggregation framework:
> db.test.insert({answers: [
... {name: 'paul', state: 'RU'},
... {name: 'steve', state: 'US'},
... {name: 'mike', state: 'DE'}]});
> db.test.insert({answers: [
... {name: 'paul', state: 'RU'},
... {name: 'steve', state: 'US'},
... {name: 'xavier', state: 'TX'}]});
db.test.aggregate([
{$unwind: "$answers"},
{$sort: {"answers.name":1}},
{$group: {_id:"$_id", answers: {$push:"$answers"}}}
]);
produces:
{
"result" : [
{
"_id" : ObjectId("5053b2477d820880c3469364"),
"answers" : [
{
"name" : "paul",
"state" : "RU"
},
{
"name" : "steve",
"state" : "US"
},
{
"name" : "xavier",
"state" : "TX"
}
]
},
{
"_id" : ObjectId("5053af9f7d820880c3469363"),
"answers" : [
{
"name" : "mike",
"state" : "DE"
},
{
"name" : "paul",
"state" : "RU"
},
{
"name" : "steve",
"state" : "US"
}
]
}
],
"ok" : 1
}
Upvotes: 36
Reputation: 11177
This might not be helpful in this context, but I thought I'd add this. You also have the option to sort it on the write which tends to be better for denormalized collections where you don't have to sort in more than one way.
I found this situation in my app when creating a feed on a user.
Meteor.users.helpers({
'addToFeed': function (gameId, pushData) {
check(pushData, FeedSchema);
Meteor.users.update({
_id: this._id,
"games.gameId": gameId
}, {
$push: {
"games.$.feed": {
$each: [pushData],
$sort: { timestamp: -1 }
}
}
});
}
});
I found it to be pretty handy because you can then use find()
and it will be sorted by your specifications by default.
Upvotes: 5
Reputation: 69663
After performing a find() you can use sort() on the return value.
db.collection.find({},{"answers.name":1}).sort({"answers.name":1})
The find would extract the name fields of all documents in the collection. The sort would then sort them by name, ascending.
http://www.mongodb.org/display/DOCS/Sorting+and+Natural+Order
Upvotes: -2