skip to Main Content

I am using GraphQL MongoDB Mongoose together and I have 2 collections .. users and categories like below.

Category.js

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

const categorySchema = new mongoose.Schema({
    title:{
        type: String,
        required: true
    },
    userid: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true,        
    },
    
    
});

module.exports = mongoose.model('Category',categorySchema);

`


User.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new mongoose.Schema({
    name:{
        type: String,
        required: true
    },
    email:{
        type: String,
        required: true,
        unique: true
    },
    password:{
        type: String,
        required: true
    }
    
});

module.exports = mongoose.model('User',userSchema);

Resolver.js

const User = require('../models/User');
const Category = require('../models/Category');

const resolvers = {
    
    getUsers: async () => {
        try {
            const users = await User.find().populate('categories');            
            return users;
        } catch(err){
            throw new Error(err);            
        }
    },
    

    
};

module.exports = resolvers;

As you can see .. I have 2 collections . and inside Categories collection.. I am adding my data with userid .. everything is working fine .. But I am unable to get categories as its keep showing null in response.

Here below is my GraphQL query.

query{
  getUsers{
    id,
    name
  }
}

And here is what I get in response evenif I have data with userid same from users collection.

{
  "data": {
    "getUsers": [
      {
        "id": "65d316bdab8179475bdb0fef",
        "name": "mittul",
        
      }
    ]
  }
}

UPDATE ..

Getting this response.

{
  "data": {
    "getUsers": null
  }
}



 try {
                var resources = {};

            const users = await User.aggregate([{
                    $group : {_id : null, totalPop: { $sum: "$pop" }}
                },{
                    $lookup: {
                        from: "Category", // from collection name
                        localField: "userid",
                        foreignField: "_id",
                        as: "categories"
                    }
                }]);
                console.log(users);
        } catch(err){
            console.log(err);
            throw new Error(err);            
        }

I have also tried below code but its giving me null in response and nothing in console.log.

  User.find().populate("categories")
        .then(users => {
            console.log(users);
            //res.send(users);
        }).catch(err => {
                    
            throw new Error(err);            
        });

Below are my 2 collections.

enter image description here

enter image description here

Can anyone guide me what I am missing here ?

Thanks

2

Answers


  1. Chosen as BEST ANSWER

    OK Guys .. Eventually I have found an answer by updating an aggregate query like below.

    getUsers: async (req,res) => {
    
           try {
                const users = await User.aggregate([
                    {
                        $match: {
                            _id: { $ne: null } // Filter out documents where _id is null
                        }
                    },
                    {
                        $lookup: {
                            from: "categories",
                            localField: "_id",
                            foreignField: "userid",
                            as: "categories"
                        }
                    },
                    {
                        $addFields: {
                            "id": { $toString: "$_id" }, // Convert _id to string and assign it to id
                            "categories": {
                                $map: {
                                    input: "$categories",
                                    as: "category",
                                    in: {
                                        id: { $toString: "$$category._id" }, // Convert _id of category to string and assign it to id
                                        title: "$$category.title"
                                    }
                                }
                            }
                        }
                    }
                ]);
                return users;
             } catch(err){
                throw new Error("Error retrieving user");            
            }
    

    This works in all the scenarios whether I add id or not for users or categories like below.

    query{
      getUsers{
        
        id,name,email,categories{
          id,
          title
        }
          
      }
    }
    

    Thanks


  2. Here is a simple aggregation that will allow you to query the users collection. In this example a $match is made for the user.name property but you can query the users for anything you want.

    Then you do a $lookup to search the categories collection for any Category that has a userid value equal to the _id value of the User that you found by searching the users collection.

    The $set stage will look at the categories array property returned from the $lookup and if its an empty array then it will be removed, otherwise it will be set it itself.

    const users = await User.aggregate([
      {
        $match: {
          _id: ObjectId("5a934e000102030405000001"),
          name: "mittul"
        }
      },
      {
        $lookup: {
          from: "categories",
          localField: "_id",
          foreignField: "userid",
          as: "categories"
        }
      },
      {
        $set: {
          "categories": {
            $cond: {
              if: {
                $eq: [
                  "$categories",
                  []
                ]
              },
              then: "$$REMOVE",
              else: "$categories"
            }
          }
        }
      }
    ])
    

    See HERE for a working example.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search