I have a collection in mongodb with mongoose schema
var collection = new Schema({
name : String,
position : Number,
category : String
});
collection.index({ category : 1, position : 1 }, { unique : true });
Now i want to fetch records in batches such that
it should group all the records on basis of category and then within each category(group), all records should be sorted on basis of position.
For example
i have following collection
[
{ name : 'Mr X', position : 34, category : 'U' },
{ name : 'Mr Y', position : 14, category : 'T' },
{ name : 'Mr G', position : 55, category : 'T' },
{ name : 'Mr I', position : 5, category : 'L' },
{ name : 'Mr D', position : 51, category : 'L' },
{ name : 'Mr P', position : 14, category : 'U' },
{ name : 'Mr P', position : 20, category : 'U' },
{ name : 'Mr E', position : 14, category : 'L' }
]
Now what should be the efficient query for this?
I am trying to fetch 3rd batch (each batch of 2 records)
db.ask.aggregate([{
$group : {
_id : "$category"
}
}, {
$sort : {
position : 1
}
}, {
$skip : 4
}, {
$limit : 2
}
])
And i am expecting output :
[
{ name : 'Mr G', position : 55, category : 'T' },
{ name : 'Mr P', position : 14, category : 'U' }
]
but actually getting none.
If fetching all records (without any batches), the expected output should be
[
{ name : 'Mr I', position : 5, category : 'L' },
{ name : 'Mr E', position : 14, category : 'L' }
{ name : 'Mr D', position : 51, category : 'L' },
{ name : 'Mr Y', position : 14, category : 'T' },
{ name : 'Mr G', position : 55, category : 'T' },
{ name : 'Mr P', position : 14, category : 'U' },
{ name : 'Mr P', position : 20, category : 'U' },
{ name : 'Mr X', position : 34, category : 'U' },
]
EDIT : I am looking for a query that is flexible to my changing requirements. what if i want to bring first category T then L then U.?
So my expected output (with limits and skip) was supposed to be
[
{ name : 'Mr I', position : 5, category : 'L' },
{ name : 'Mr P', position : 14, category : 'U' }
]
As far as I understand your requirements, you do not want to group at all but just want to sort by two fields and then do more or less some kind of paging.
That said, with the following aggregation pipeline I got your desired result.
db.ask.aggregate([
{
$sort : {
category : 1,
position : 1
}
},
{
$project : {
_id : 0,
category : 1,
position : 1,
name : 1
}
},
{
$skip : 4
},
{
$limit : 2
},
])
Well, you need to group on compound key to get desired result.
db.collection.aggregate([
{$group : { _id : {category:"$category", position:"$position", name:"$name"}}},
{$project:{_id:0, category:"$_id.category", name:"$_id.name", position:"$_id.position"}},
{$sort : {"category" : 1, position:1} },
{$skip : 4 },
{$limit : 2 }
])
This will print:
{
"category" : "T",
"name" : "Mr G",
"position" : 55.0
}
{
"category" : "U",
"name" : "Mr P",
"position" : 14.0
}
there is no need to group and other aggregation stages just sort on correct fields
we can have normal
query
db.codofoode.find()
.sort({
category : 1,
position : 1
}).skip(4).limit(2)
or aggregate
db.codofoode.aggregate([
{
$sort : {
category:1, position : 1
}
},
{
$skip : 4
},
{
$limit : 2
}])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.