Search code examples
node.jsmongodbgraphqlmernexpress-graphql

How to get the Populated values of a model in GraphqQL list without _id reference?


I have a Users model with some fields and reference to "Skills" model.

The models are look like this below

1.Users.js (users model)

 const mongoose = require('mongoose');
 const Schema = mongoose.Schema;

 const UsersSchema = new Scheam({
     name: { type : String },
     email: { type : String },
     address: { type : String },

     Skills: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Skills' }],
 })

 module.exports = mongoose.model('Users', UsersSchema);

2.Skills Model

const mongoose = require('mongoose')
const Schema = mongoose.Schema;

const SkillsSchema = new Schema({
   name : { type: String },
});

module.exports = mongoose.model('Skills', SkillsSchema);

I am creating the new user with dropdown menu of skills selection storing the id's of the skills in users model.

And getting the skills by populating the Users model like this in node js app.

  export function getUser(req, res) {
     console.log('getUser');
     console.log('req.body',req.body);
     Users.findOne({_id: req.body.user_id}).populate('skills').exec(function(err, usr_doc){ 
       if(err) {
          res.json({
             status: 401,
             message: 'something went wrong!',
             err: err,
          });
       } else if (!err && usr_doc != null) {
           res.json({
               status: 200,
               message: 'User details found!',
               data: {_id: usr_doc._id, skills: usr_doc.skills,name: usr_doc.name,token: usr_doc.token},
           })
       }
     })//Users.findOne end
  }

The above code is working fine for normal rest api.

Here I try to create the Same api using GraphQL server of express-graphql in Nodejs.

The code look like this.

3.Schema.js

 const graphql = require('graphql');
 const Users = require('../models/Users');
 const Skills = require('../models/Skills');

 const { 
    GraphQLObjectType,
    GraphQLInt,
    GraphQLFloat,
    GraphQLString, 
    GraphQLSchema,
    GraphQLID,
    GraphQLList,
    GraphQLNonNull,
    GraphQLBoolean,
    GraphQLObject
 } = graphql;

 const UsersType = new GraphQLObjectType ({
       name: 'Users',
       fields: () => ({
            id: {type: GraphQLID},
            name: { type : GraphQLString },
            email: { type : GraphQLString },
            **skills: {
                type: new GraphQLList(SkillsType),
                resolve(parent, args){
                  //Here I need to know how to get the skills name of the users
                }
            }**
       })

   const SkillsType = new GraphQLObjectType({
       name: 'Skills',
       fields: () => ({
          name: { type : GraphQLString },
       })
   })    

At present I didn't use any reference id in skills model, only name. I want to get the skill names of the Users.

If i use the below, I am getting all of the skill names instead of user particular or populated skill names.

   skills : {
     type: new GraphQLList(SkillsType),
        resolve(parent, args){
            return Skills.find({})
        } 

Please provide any suggestions regarding this.

I can give more information if you need.


Solution

  • To get the skills of a user, instead of Skills.find({}) which returns all the documents present in the skills collection, add a condition there with the parent object.

    The parent object, which contains result from the resolver on the parent field here. So skills, a child resolver, can be written as:

     skills: {
         type: new GraphQLList(SkillsType),
         resolve(parent, args) {
             return await Skills.find({"_id": {$in: parent.skills} }) }
     }