Reputation: 753
I have a collection called 'assignments' that is like below:
[
{
"_id" : ObjectId("60e1d5824a5b1c32c069c864"),
"course" : ObjectId("5ffeec372b2234556439d1da"),
"students" : [
{
"_id" : ObjectId("60e1d5824a5b1c32c069c865"),
"user" : ObjectId("601e489fb77a9fabf85ea306"),
"section" : ObjectId("6002fae3e58bc750b4394229")
},
{
"_id" : ObjectId("60e1d5824a5b1c32c069c866"),
"user" : ObjectId("601e48cdb77a9fabf85ea307"),
"section" : ObjectId("6002fae3e58bc750b4394229")
}
]
},
{
"_id" : ObjectId("60e1c8a6a2886142b8b86523"),
"students" : [
],
"course" : ObjectId("5ffeec372b2234556439d1da"),
}]
Here you see an array named "students". I want to get details of "user" and "section" while querying the "assignments".
I am using graphql. And 'students' is a field of the type 'Assignment' like below:
type AssignmentStudent{
user:User
section:Section
}
type Assignment{
id:ID!
createdAt:Date
updatedAt:Date
course:Course!
students:[AssignmentStudent!]
}
When I query I get information of 'course', but for 'students' I am not sure what to do.
In 'Assignment' resolver I have written query for 'course' like this:
Assignment: {
async course(parent, { input }, context, info) {
try {
return await Course.findById(parent.course)
} catch (err) {
console.log('err', err.message);
}
}
}
For actual result of 'stuents' what should I do ?
Upvotes: 0
Views: 635
Reputation: 51
I saw you already found a solution that works for you, however another method is to use mongoose's populate, as you can specify specifically what you want it to return.
Assignment: {
async course(parent, {
input
}, context, info) {
try {
return await Course.findById(parent.course).populate('students', 'user section')
} catch (err) {
console.log('err', err.message);
}
}
}
Since you're already storing them as ObjectIds (with reference I assume), populate will populate the field you specify, in this case students - and the second argument added will further specify what to return from it. If you have issues with populate even tho your code is correct, sometimes adding .execPopulate()
at the end of it will do the trick (can't explain this one).
Some other questions/articles on populating in mongoose (and specifiying fields):
Hope that helps!
Upvotes: 1
Reputation: 753
Actually, I went for an approach like below which worked for me. I am not sure whether this approach is efficient or not, but it worked.
async students(parent, { input }, context, info) {
try {
const promises = parent.students.map(async (item) => {
return {
id: item.id,
user: await User.findById(item.user),
section: await Section.findById(item.section)
}
});
return Promise.all(promises);
} catch (err) {
console.log('err', err.message);
}
},
Upvotes: 0
Reputation: 16
You just need to traverse students array and for every item make similar findOne. Or you can filter ids and make find({ _id: { $in: ['1', '2', '3'] } }), and then attach result.
Upvotes: 0