How to sort a populated two level deep subdocuments array with mongoose [duplicate]Mongodb sort inner array$lookup multiple levels without $unwind?Mongoose: deep population (populate a populated field)Mongoose sort by populated fieldMongoose query array of ObjectId's for one ObjectIdMongoose sorting subdocument populatedCast to objectid failed for value when calling findOne and populateMongoose Population not returning all fieldsHandling mongoose population exceptionsMongoose populate sort optionMongoose Populate after AggregateHow to handle multilevel inheritance in node js and mongo database

How to determine what is the correct level of detail when modelling?

Should I include salary information on my CV?

Does ultrasonic bath cleaning damage laboratory volumetric glassware calibration?

When is it ok to add filler to a story?

How would a order of Monks that renounce their names communicate effectively?

Intuitively, why does putting capacitors in series decrease the equivalent capacitance?

Should I tell my insurance company I have an unsecured loan for my new car?

Dold-Kan correspondence in the category of symmetric spectra

Going to get married soon, should I do it on Dec 31 or Jan 1?

How do I find and plot the intersection of these three surfaces?

How can I check type T is among parameter pack Ts... in C++?

Was touching your nose a greeting in second millenium Mesopotamia?

Confusion about multiple information Sets

Does anycast addressing add additional latency in any way?

How come I was asked by a CBP officer why I was in the US when leaving?

Why does the A-4 Skyhawk sit nose-up when on ground?

Should I report a leak of confidential HR information?

Derivative of an algebraic power series in positive characteristic

Averting Real Women Don’t Wear Dresses

Find smallest index that is identical to the value in an array

A player is constantly pestering me about rules, what do I do as a DM?

How should I behave to assure my friends that I am not after their money?

Set vertical spacing between two particular items

Zombie Diet, why humans



How to sort a populated two level deep subdocuments array with mongoose [duplicate]


Mongodb sort inner array$lookup multiple levels without $unwind?Mongoose: deep population (populate a populated field)Mongoose sort by populated fieldMongoose query array of ObjectId's for one ObjectIdMongoose sorting subdocument populatedCast to objectid failed for value when calling findOne and populateMongoose Population not returning all fieldsHandling mongoose population exceptionsMongoose populate sort optionMongoose Populate after AggregateHow to handle multilevel inheritance in node js and mongo database






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








1
















This question already has an answer here:



  • $lookup multiple levels without $unwind?

    1 answer



  • Mongodb sort inner array

    1 answer



I'm developping an api with mongoose and nodejs.



Basically there is a Course Model, Student Model and Group Model. For every course there is two fields in course document:



. Field "students": array of objectids referencing Student Model.



. Field "groups": array of subdocuments, each subdocument has a "groupId" field referencing Group Model and a "students" field: an array of objectids referencing Student Model. These are the students enrolled in the group by course.



I can get the sorted student list by course, but I can't get this list by group. I can get the list unsorted, but not sorted.



These are my main schemas:



Group Model -> groups collection:



const groupSchema = new mongoose.Schema(
name:
type: String,
required: true,
unique: true

)


Student Model -> students collection:



const studentSchema = new mongoose.Schema(
name:
type: String,
required: true,
index:true
,
firstName:
type: String,
required: true,
index:true
,
lastName:
type: String,
required: true,
index:true

)


Course Model -> courses collection:



const courseSchema = new mongoose.Schema(
name:
type: String,
required: true,
index: true
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],
groups: [

groupId:
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],

]
)


Using next query I get an alphabetically sorted student list by course, even I can filter with "where" without problems:



const query = await Course.findById(courseId)
.select('students')
.populate(
path: 'students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
options:
sort:
firstName: 1,
lastName: 1,
name: 1


)


This query is fine,but I want another query to return the ordered student list by group and course. I'm using a similar query, but with a nested subdocuments array:



 const query = await Course.findById(courseId)
.where('groups.groupId').equals(groupId)
.select('groups.$.students')
.populate(
path: 'groups.students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
// options:
// sort:
// firstName: 1,
// lastName: 1,
// name: 1
//
//
)


This way I get the student list, but unsorted. If I uncomment the options to sort the populated list, I get the error:



"Cannot populate with sort on path groups.students because it is a subproperty of a document array".



I'm newbie in mongodb, before I worked with sql databases, but I'm learning mongodb with mongoose. I don't know if my schema design is the best to get what I want.



As this is not working, to fix the problem I apply the "sort" method to the query to sort, like this:



 query.groups[0].students.sort((st1, st2) => 
if (st1.firstName > st2.firstName) return 1
if (st1.lastName > st2.lastName) return 1
if (st1.name > st2.name) return 1
return -1
)


Is there a way to get this using the query and/or populate methods?



Following the expert advices about mongodb aggregation framework I find out my first approach to solve my problem. The aggregate I've used:



db.courses.aggregate([
$match: _id: ObjectId("5c6d43c98068bc0836a62b65") ,
$project:
_id: 0,
groups: '$groups'

,
$unwind: "$groups" ,
$match: 'groups.groupId': ObjectId("5c94b0d81ce16357d74549dd") ,
$project:
students: '$groups.students'
,
$unwind: '$students' ,
$lookup:
from: "students",
localField: "students",
foreignField: "_id",
as: "students"
,
$project:
id: $arrayElemAt: [ "$students._id", 0 ] ,
nie: $arrayElemAt: [ "$students.nie", 0 ] ,
name: $arrayElemAt: [ "$students.name", 0 ] ,
firstName: $arrayElemAt: [ "$students.firstName", 0 ] ,
lastName: $arrayElemAt: [ "$students.lastName", 0 ]
,
$sort: firstName: 1, lastName: 1, name: 1
])









share|improve this question















marked as duplicate by Neil Lunn mongodb
Users with the  mongodb badge can single-handedly close mongodb questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Mar 25 at 11:45


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.













  • 2





    As the error notes, populate() does not work on embedded documents. The only way to get MongoDB to return a "sorted array" is through an aggregation pipeline. Likewise, $lookup is better suited to modern deployments than populate(). In reality though, if you don't want to do anything else with the inner arrays than sort them, you probably should just post process the results. Ideally coming from a nested $lookup, which can sort it's result arrays. All of those concepts are demonstrated on the linked answers. Particular with the $lookup case, which also shows populate approaches

    – Neil Lunn
    Mar 25 at 11:50

















1
















This question already has an answer here:



  • $lookup multiple levels without $unwind?

    1 answer



  • Mongodb sort inner array

    1 answer



I'm developping an api with mongoose and nodejs.



Basically there is a Course Model, Student Model and Group Model. For every course there is two fields in course document:



. Field "students": array of objectids referencing Student Model.



. Field "groups": array of subdocuments, each subdocument has a "groupId" field referencing Group Model and a "students" field: an array of objectids referencing Student Model. These are the students enrolled in the group by course.



I can get the sorted student list by course, but I can't get this list by group. I can get the list unsorted, but not sorted.



These are my main schemas:



Group Model -> groups collection:



const groupSchema = new mongoose.Schema(
name:
type: String,
required: true,
unique: true

)


Student Model -> students collection:



const studentSchema = new mongoose.Schema(
name:
type: String,
required: true,
index:true
,
firstName:
type: String,
required: true,
index:true
,
lastName:
type: String,
required: true,
index:true

)


Course Model -> courses collection:



const courseSchema = new mongoose.Schema(
name:
type: String,
required: true,
index: true
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],
groups: [

groupId:
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],

]
)


Using next query I get an alphabetically sorted student list by course, even I can filter with "where" without problems:



const query = await Course.findById(courseId)
.select('students')
.populate(
path: 'students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
options:
sort:
firstName: 1,
lastName: 1,
name: 1


)


This query is fine,but I want another query to return the ordered student list by group and course. I'm using a similar query, but with a nested subdocuments array:



 const query = await Course.findById(courseId)
.where('groups.groupId').equals(groupId)
.select('groups.$.students')
.populate(
path: 'groups.students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
// options:
// sort:
// firstName: 1,
// lastName: 1,
// name: 1
//
//
)


This way I get the student list, but unsorted. If I uncomment the options to sort the populated list, I get the error:



"Cannot populate with sort on path groups.students because it is a subproperty of a document array".



I'm newbie in mongodb, before I worked with sql databases, but I'm learning mongodb with mongoose. I don't know if my schema design is the best to get what I want.



As this is not working, to fix the problem I apply the "sort" method to the query to sort, like this:



 query.groups[0].students.sort((st1, st2) => 
if (st1.firstName > st2.firstName) return 1
if (st1.lastName > st2.lastName) return 1
if (st1.name > st2.name) return 1
return -1
)


Is there a way to get this using the query and/or populate methods?



Following the expert advices about mongodb aggregation framework I find out my first approach to solve my problem. The aggregate I've used:



db.courses.aggregate([
$match: _id: ObjectId("5c6d43c98068bc0836a62b65") ,
$project:
_id: 0,
groups: '$groups'

,
$unwind: "$groups" ,
$match: 'groups.groupId': ObjectId("5c94b0d81ce16357d74549dd") ,
$project:
students: '$groups.students'
,
$unwind: '$students' ,
$lookup:
from: "students",
localField: "students",
foreignField: "_id",
as: "students"
,
$project:
id: $arrayElemAt: [ "$students._id", 0 ] ,
nie: $arrayElemAt: [ "$students.nie", 0 ] ,
name: $arrayElemAt: [ "$students.name", 0 ] ,
firstName: $arrayElemAt: [ "$students.firstName", 0 ] ,
lastName: $arrayElemAt: [ "$students.lastName", 0 ]
,
$sort: firstName: 1, lastName: 1, name: 1
])









share|improve this question















marked as duplicate by Neil Lunn mongodb
Users with the  mongodb badge can single-handedly close mongodb questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Mar 25 at 11:45


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.













  • 2





    As the error notes, populate() does not work on embedded documents. The only way to get MongoDB to return a "sorted array" is through an aggregation pipeline. Likewise, $lookup is better suited to modern deployments than populate(). In reality though, if you don't want to do anything else with the inner arrays than sort them, you probably should just post process the results. Ideally coming from a nested $lookup, which can sort it's result arrays. All of those concepts are demonstrated on the linked answers. Particular with the $lookup case, which also shows populate approaches

    – Neil Lunn
    Mar 25 at 11:50













1












1








1









This question already has an answer here:



  • $lookup multiple levels without $unwind?

    1 answer



  • Mongodb sort inner array

    1 answer



I'm developping an api with mongoose and nodejs.



Basically there is a Course Model, Student Model and Group Model. For every course there is two fields in course document:



. Field "students": array of objectids referencing Student Model.



. Field "groups": array of subdocuments, each subdocument has a "groupId" field referencing Group Model and a "students" field: an array of objectids referencing Student Model. These are the students enrolled in the group by course.



I can get the sorted student list by course, but I can't get this list by group. I can get the list unsorted, but not sorted.



These are my main schemas:



Group Model -> groups collection:



const groupSchema = new mongoose.Schema(
name:
type: String,
required: true,
unique: true

)


Student Model -> students collection:



const studentSchema = new mongoose.Schema(
name:
type: String,
required: true,
index:true
,
firstName:
type: String,
required: true,
index:true
,
lastName:
type: String,
required: true,
index:true

)


Course Model -> courses collection:



const courseSchema = new mongoose.Schema(
name:
type: String,
required: true,
index: true
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],
groups: [

groupId:
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],

]
)


Using next query I get an alphabetically sorted student list by course, even I can filter with "where" without problems:



const query = await Course.findById(courseId)
.select('students')
.populate(
path: 'students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
options:
sort:
firstName: 1,
lastName: 1,
name: 1


)


This query is fine,but I want another query to return the ordered student list by group and course. I'm using a similar query, but with a nested subdocuments array:



 const query = await Course.findById(courseId)
.where('groups.groupId').equals(groupId)
.select('groups.$.students')
.populate(
path: 'groups.students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
// options:
// sort:
// firstName: 1,
// lastName: 1,
// name: 1
//
//
)


This way I get the student list, but unsorted. If I uncomment the options to sort the populated list, I get the error:



"Cannot populate with sort on path groups.students because it is a subproperty of a document array".



I'm newbie in mongodb, before I worked with sql databases, but I'm learning mongodb with mongoose. I don't know if my schema design is the best to get what I want.



As this is not working, to fix the problem I apply the "sort" method to the query to sort, like this:



 query.groups[0].students.sort((st1, st2) => 
if (st1.firstName > st2.firstName) return 1
if (st1.lastName > st2.lastName) return 1
if (st1.name > st2.name) return 1
return -1
)


Is there a way to get this using the query and/or populate methods?



Following the expert advices about mongodb aggregation framework I find out my first approach to solve my problem. The aggregate I've used:



db.courses.aggregate([
$match: _id: ObjectId("5c6d43c98068bc0836a62b65") ,
$project:
_id: 0,
groups: '$groups'

,
$unwind: "$groups" ,
$match: 'groups.groupId': ObjectId("5c94b0d81ce16357d74549dd") ,
$project:
students: '$groups.students'
,
$unwind: '$students' ,
$lookup:
from: "students",
localField: "students",
foreignField: "_id",
as: "students"
,
$project:
id: $arrayElemAt: [ "$students._id", 0 ] ,
nie: $arrayElemAt: [ "$students.nie", 0 ] ,
name: $arrayElemAt: [ "$students.name", 0 ] ,
firstName: $arrayElemAt: [ "$students.firstName", 0 ] ,
lastName: $arrayElemAt: [ "$students.lastName", 0 ]
,
$sort: firstName: 1, lastName: 1, name: 1
])









share|improve this question

















This question already has an answer here:



  • $lookup multiple levels without $unwind?

    1 answer



  • Mongodb sort inner array

    1 answer



I'm developping an api with mongoose and nodejs.



Basically there is a Course Model, Student Model and Group Model. For every course there is two fields in course document:



. Field "students": array of objectids referencing Student Model.



. Field "groups": array of subdocuments, each subdocument has a "groupId" field referencing Group Model and a "students" field: an array of objectids referencing Student Model. These are the students enrolled in the group by course.



I can get the sorted student list by course, but I can't get this list by group. I can get the list unsorted, but not sorted.



These are my main schemas:



Group Model -> groups collection:



const groupSchema = new mongoose.Schema(
name:
type: String,
required: true,
unique: true

)


Student Model -> students collection:



const studentSchema = new mongoose.Schema(
name:
type: String,
required: true,
index:true
,
firstName:
type: String,
required: true,
index:true
,
lastName:
type: String,
required: true,
index:true

)


Course Model -> courses collection:



const courseSchema = new mongoose.Schema(
name:
type: String,
required: true,
index: true
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],
groups: [

groupId:
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
,
students: [

type: mongoose.Schema.Types.ObjectId,
ref: 'Student'

],

]
)


Using next query I get an alphabetically sorted student list by course, even I can filter with "where" without problems:



const query = await Course.findById(courseId)
.select('students')
.populate(
path: 'students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
options:
sort:
firstName: 1,
lastName: 1,
name: 1


)


This query is fine,but I want another query to return the ordered student list by group and course. I'm using a similar query, but with a nested subdocuments array:



 const query = await Course.findById(courseId)
.where('groups.groupId').equals(groupId)
.select('groups.$.students')
.populate(
path: 'groups.students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
// options:
// sort:
// firstName: 1,
// lastName: 1,
// name: 1
//
//
)


This way I get the student list, but unsorted. If I uncomment the options to sort the populated list, I get the error:



"Cannot populate with sort on path groups.students because it is a subproperty of a document array".



I'm newbie in mongodb, before I worked with sql databases, but I'm learning mongodb with mongoose. I don't know if my schema design is the best to get what I want.



As this is not working, to fix the problem I apply the "sort" method to the query to sort, like this:



 query.groups[0].students.sort((st1, st2) => 
if (st1.firstName > st2.firstName) return 1
if (st1.lastName > st2.lastName) return 1
if (st1.name > st2.name) return 1
return -1
)


Is there a way to get this using the query and/or populate methods?



Following the expert advices about mongodb aggregation framework I find out my first approach to solve my problem. The aggregate I've used:



db.courses.aggregate([
$match: _id: ObjectId("5c6d43c98068bc0836a62b65") ,
$project:
_id: 0,
groups: '$groups'

,
$unwind: "$groups" ,
$match: 'groups.groupId': ObjectId("5c94b0d81ce16357d74549dd") ,
$project:
students: '$groups.students'
,
$unwind: '$students' ,
$lookup:
from: "students",
localField: "students",
foreignField: "_id",
as: "students"
,
$project:
id: $arrayElemAt: [ "$students._id", 0 ] ,
nie: $arrayElemAt: [ "$students.nie", 0 ] ,
name: $arrayElemAt: [ "$students.name", 0 ] ,
firstName: $arrayElemAt: [ "$students.firstName", 0 ] ,
lastName: $arrayElemAt: [ "$students.lastName", 0 ]
,
$sort: firstName: 1, lastName: 1, name: 1
])




This question already has an answer here:



  • $lookup multiple levels without $unwind?

    1 answer



  • Mongodb sort inner array

    1 answer







mongodb mongoose schema populate






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 26 at 9:44







Francisco Mora Sánchez

















asked Mar 25 at 11:40









Francisco Mora SánchezFrancisco Mora Sánchez

63 bronze badges




63 bronze badges




marked as duplicate by Neil Lunn mongodb
Users with the  mongodb badge can single-handedly close mongodb questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Mar 25 at 11:45


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









marked as duplicate by Neil Lunn mongodb
Users with the  mongodb badge can single-handedly close mongodb questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Mar 25 at 11:45


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









  • 2





    As the error notes, populate() does not work on embedded documents. The only way to get MongoDB to return a "sorted array" is through an aggregation pipeline. Likewise, $lookup is better suited to modern deployments than populate(). In reality though, if you don't want to do anything else with the inner arrays than sort them, you probably should just post process the results. Ideally coming from a nested $lookup, which can sort it's result arrays. All of those concepts are demonstrated on the linked answers. Particular with the $lookup case, which also shows populate approaches

    – Neil Lunn
    Mar 25 at 11:50












  • 2





    As the error notes, populate() does not work on embedded documents. The only way to get MongoDB to return a "sorted array" is through an aggregation pipeline. Likewise, $lookup is better suited to modern deployments than populate(). In reality though, if you don't want to do anything else with the inner arrays than sort them, you probably should just post process the results. Ideally coming from a nested $lookup, which can sort it's result arrays. All of those concepts are demonstrated on the linked answers. Particular with the $lookup case, which also shows populate approaches

    – Neil Lunn
    Mar 25 at 11:50







2




2





As the error notes, populate() does not work on embedded documents. The only way to get MongoDB to return a "sorted array" is through an aggregation pipeline. Likewise, $lookup is better suited to modern deployments than populate(). In reality though, if you don't want to do anything else with the inner arrays than sort them, you probably should just post process the results. Ideally coming from a nested $lookup, which can sort it's result arrays. All of those concepts are demonstrated on the linked answers. Particular with the $lookup case, which also shows populate approaches

– Neil Lunn
Mar 25 at 11:50





As the error notes, populate() does not work on embedded documents. The only way to get MongoDB to return a "sorted array" is through an aggregation pipeline. Likewise, $lookup is better suited to modern deployments than populate(). In reality though, if you don't want to do anything else with the inner arrays than sort them, you probably should just post process the results. Ideally coming from a nested $lookup, which can sort it's result arrays. All of those concepts are demonstrated on the linked answers. Particular with the $lookup case, which also shows populate approaches

– Neil Lunn
Mar 25 at 11:50












0






active

oldest

votes



















0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes

Popular posts from this blog

Obelisk of Theodosius Contents History Description Notes Bibliography Further reading External links Navigation menuAge of spirituality : late antique and early Christian art, third to seventh centuryOver 60 picturesObelisks of the World41°00′21.24″N 28°58′31.43″E / 41.0059000°N 28.9753972°E / 41.0059000; 28.97539727724550-7235741376235741376

밀양 대씨 역사 각주 함께 보기 둘러보기 메뉴밀양 대씨

1973년 목차 사건 문화 탄생 사망 노벨상 달력 둘러보기 메뉴