1

I'm wiring up a graphQL backend with mongoose and I am having trouble with some of the conventions of mongoose for a nested query. If I have the following field in the root query:

course: {
  type: CourseType,
  args: { id: { type: new GraphQLNonNull(GraphQLID) } },
  resolve(parentValue, { id }) {
    return Course.findById(id);
  },
},

A Course Type of this:

const CourseType = new GraphQLObjectType({
  name: 'CourseType',
  fields: () => ({
    id: { type: GraphQLID },
    sections: {
      type: new GraphQLList(SectionType),
      resolve(parentValue) {
        return Course.findSections(parentValue._id);
      }
    }
  }),
});

And my model looks like this:

const CourseSchema = new Schema({
  _id: { type: String },
  sections: [{
    type: Schema.Types.String,
    ref: 'Section'
  }],
});

CourseSchema.statics.findSections = function(id) {
  return this.findById(id)
    .populate('Sections')
    .then(course => {
      return course.sections
    });
}

mongoose.model('Course', CourseSchema, 'Courses');

const SectionSchema = new Schema({
  _id: { type: String },
  course: {
    type: Schema.Types.String,
    ref: 'Course',
  },
});

mongoose.model('Section', SectionSchema, 'Sections');

I would expect that I could run a query like this:

query {
 course(id: "4Zpm8zrZYqdbr2i4t") {
  id
  sections {
    id
  }
 }
}

And I should get back a given course with all of its sections. The sections come back as an empty array while the course comes back as expected. I can tell that if I look in the findSections method that it has the proper id, but populate doesn't seem to fetch the sections.

I have a feeling that I'm running into some issue with how mongoose uses its conventions for how to name stuff but I can't for the life of me figure out what is going on. Here is what my mongoDB looks like:

MongoDB:
Courses: { _id: "4Zpm8zrZYqdbr2i4t" }
Sections: { _id: "00000000000000000", courseId: "4Zpm8zrZYqdbr2i4t" }

1 Answer 1

1

One thing that does not look correct. You want to populate for the path sections but the string is in capital letter. See the docu.

So it should look like this:

CourseSchema.statics.findSections = function(id) {
  return this.findById(id)
    .populate('sections') // lower case
    .then(course => {
      return course.sections
    });
}

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks that did it! I didn't realize that my courses needs an array of all the sections AND it isn't enough to have all my sections have a courseId.
Just as a final question to really make sure I understand it- would it be possibly to have a query for Section.findById in your code block above so that we can search a child collection for ids that match the parent we are querying for?
Im not perfectly sure what you mean. But maybe you mean the in functionality of the mongoDB.
Sorry I'll try once more: 1 course has many sections. Each section has a courseId. Can I find out the sections a course has without saving the sections:[sectionId1, sectionId2...] in course? Instead I would search the sections collection for all { courseId=course._id } so go the other way?
Sure just use find. E.G. SectionModel.find({"course_id": <given course id>}, (error, sections) => { // do something}). But i suggest you let it like this because i think it is one of the big advantages of mongoDB and what if you want to add a section to different courses?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.