Reputation: 2184
i am having 2 documents in score collections(student)databases like below in mongodb database.
{
id: 2,
type: 'newname',
subs: [
{ time: 20, val: 'b' },
{ time: 12, val: 'a' },
{ time: 30, val: 'c' }
] }, {
id: 1,
type: 'strs',
subs: [
{ time: 50, val: 'be' },
{ time: 1, val: 'ab' },
{ time: 20, val: 'cs' }
] }
How to construct a query to get the below result
{
id: 1,
type: 'strs',
subs: [
{ time: 1, val: 'ab' },
{ time: 20, val: 'cs' },
{ time: 50, val: 'be' }
]
},
{
id: 2,
type: 'newname',
subs: [
{ time: 12, val: 'a' },
{ time: 20, val: 'b' },
{ time: 30, val: 'c' }
]
}
ie: a query for find the documents based on time and have to sort the results on 2 criteria
Upvotes: 6
Views: 16810
Reputation: 36094
It is possible when use in sequence $unwind
> $sort
> $group
specialty for array,
subs
db.collection.aggregate([
{ $unwind: "$subs" },
subs.time
in ascending (1) order { $sort: { "subs.time": 1 } },
id
, and re-construct subs
array using $push
objects and other fields remain using $first
{
$group: {
_id: "$id",
id: { $first: "$id" },
type: { $first: "$type" },
subs: { $push: "$subs" }
}
},
_id
{ $project: { _id: 0 } },
$sort
by id
in ascending order { $sort: { id: 1 } }
])
Upvotes: 0
Reputation: 525
Strangely, MongoDB does not provide any method to sort sub documents by querying it. It seems you will have to update the natural sort order of the sub docs as shown below :
If these are the only 2 docs in your collection, write below query :
db.test.update( {}, {$push : {"subs" :{$each : [] , $sort : {time : -1}}}})
and then run query to sort on ID itself :
db.test.find().sort({'id':1}).pretty()
You will get below output.
{
"id" : 1,
"type" : "strs",
"subs" : [
{
"time" : 50,
"val" : "be"
},
{
"time" : 20,
"val" : "cs"
},
{
"time" : 1,
"val" : "ab"
}
]
}
{
"id" : 2,
"type" : "newname",
"subs" : [
{
"time" : 30,
"val" : "c"
},
{
"time" : 20,
"val" : "b"
},
{
"time" : 12,
"val" : "a"
}
]
}
Hope it solves you situation. Below is the reference :
Upvotes: 3
Reputation: 971
You can use cursor.sort()
to sort on multiple fields (basically a combo) at the same time but I don't think it works when sorting on both a document and a subdocument field at the same time.
If you were to sort on two different fields of the top document or on two different fields of a subdocument then it would be fine i guess.
So you can get a similar output using the aggregation framework. All you have to do is basically break down the arrays of the subs
field and then sort them.
You could do something like:
db.col.aggregate({$unwind:'subs'}, {$sort:{id:1,'subs.time':1}});
With the above code you should get an output similar to this:
{
id: 1,
type: 'strs',
subs:
{ time: 1, val: 'ab' }
},{
id: 1,
type: 'strs',
subs:
{ time: 20, val: 'cs' }
},{
id: 1,
type: 'strs',
subs:
{ time: 50, val: 'be' }
},{
id: 2,
type: 'newname',
subs:
{ time: 12, val: 'a' }
},{
id: 2,
type: 'newname',
subs:
{ time: 20, val: 'b' }
},{
id: 2,
type: 'newname',
subs:
{ time: 30, val: 'c' }
}
Upvotes: 7
Reputation: 252
You can use cursor.sort(sort)
For Exapmle:
db.collection.find().sort( { 'id': 1 } )
to sort the results using id in ascending order.
For more details refer the following link. http://docs.mongodb.org/manual/reference/method/cursor.sort/
Upvotes: -2