amalrik
amalrik

Reputation: 31

Mongoose Populate with API request and Postman, return empty array?

I have created an api with nodejs, mongodb/mongoose and express, to make CRUD request to interact with json data, more specifically, with two mongodb collections (1: datas 2: produits).

The "datas" collection is bind to an "User" schema.
The "produits" collection is bind to an "product" schema.

My problem is:
In "User" schema, I have a place Productlist which will get/save the ID of a product, from produits collection.

My User schema look like this:

//Get module
var mongoose = require('mongoose'); 
var prodSch = require('../models/productSchema');
var Schema = mongoose.Schema;

//Create user shema
 var user = new Schema({
 "UIDUser": String,
 "IDUser": String,
 "UIDACL": String,
 "DatasUser": {
     "acl_user_id": String,
     "prenom": String,
     "role": String,
     "nom": String,
     "pseudo": String,
     "email": String
 },
   "Productlist" : [{ type: Schema.Types.ObjectId, ref: 'prodSch'}],
   "Data_Unknown": {}
 },
 {
     collection : 'datas' // define the collection to use
 });

 //Export schema
 module.exports = mongoose.model('userSch', user);

So my User schema is saved in dataschema.js.

I have on a different file productSchema.js a product schema.

//Get module
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

//Create product shema
var Product = new Schema({
    "product": String,
    "UIDProduct": String,
    "HashKey": String,
    "EAN13": String,
    "UIDReader": String,
    "URL": String,
    "readers_Label": String,
    "devices_Label": String,
    "EntryCatalis": [{
        "TETITISC": String,
        "TEGRDIMG": String,
        "TEPETIMG": String,
        "TEREFIMG": String,
        "LISCEISC": String
    }],

    "URLHeader": { "Content-Length": Number, "Last-Modified": String},
    "ExpireOn": String,
    "Data_Unknown": {}
},
{
    collection : 'produits' // Define the collection to use
});

// exports schema
module.exports = mongoose.model('prodSch', Product);

I need to save in User Productlist the ID of all the product created, and I need to use populate to do that.

ex:

product{name: tomato, origin: spain, id: 001}

user{fname: john, lname: doe, Productlist: 001} //id of the product, saved 
                                                //via populate 

I have two different files to create/initialise the CRUD function of my User schema and my Product schema.

In these files I have all the functions for post, get, delete, get_by_Id, etc... but separated in two files.

So to populate Productlist I have defined the Schema. Types and the ref of the product schema in dataschema.js:

 "Productlist" : [{ type: Schema.Types.ObjectId, ref: 'prodSch'}]

Then in routeUser.js who manage the CRUD functions for dataschema.js I tried to do some test in the .post function to populate Productlist.

ex:

.post(function(req, res){
    var newData = new userSch();

    newData.UIDUser = req.body.UIDUser;
    newData.IDUser = req.body.IDUser;
    newData.UIDACL = req.body.UIDACL;
    newData.DatasUser = req.body.DatasUser;
    newData.acl_user_id = req.body.acl_user_id;
    newData.prenom = req.body.prenom;
    newData.role = req.body.role;
    newData.nom = req.body.nom;
    newData.pseudo = req.body.pseudo;
    newData.email = req.body.email;
    newData.Data_Unknown = req.body.Data_Unknown;

    newData.save(function(err){         
            if (err)
                res.status(400).send(err);

            userSch.find().populate('Productlist').exec(function (err, story) {
                if (err) return handleError(err);
                console.log('%s', userSch.Productlist);
                res.json({message: "data created successfully"});
            });
    });
});

I tried the test also with the file routeProduct.js who manage the CRUD functions for the productSchema.js.

So with this, I can't get the product ID in Productlist in my user schema. I have searched many tutorials about populate, but I never found the right one for my problem.

I understand the idea, but I don't know how to use it correctly.

Can you please help me to understand what is my error, and how to use populate on my Productlist correctly?

Edit:

I made some change to my code, i can make my request without any error, but my Populate still doesn't work.

This is the line i have modified:

.post(function(req, res){

    var newData = new prodSch();

    newData.product         = req.body.product;
    newData.UIDProduct        = req.body.UIDProduct;
    newData.HashKey           = req.body.HashKey;
    newData.EAN13             = req.body.EAN13;
    newData.UIDReader         = req.body.UIDReader;
    newData.URL               = req.body.URL;
    newData.readers_Label     = req.body.readers_Label;
    newData.devices_Label     = req.body.devices_Label;
    newData.EntryCatalis      = req.body.EntryCatalis;
    newData.TETITISC          = req.body.TETITISC;
    newData.TEGRDIMG          = req.body.TEGRDIMG;
    newData.TEPETIMG          = req.body.TEPETIMG;
    newData.TEREFIMG          = req.body.TEREFIMG;
    newData.LISCEISC          = req.body.LISCEISC;
    newData.URLHeader         = req.body.URLHeader;
    newData['Content-Length'] = req.body['Content-Length'];
    newData['Last-Modified']  = req.body['Last-Modified'];
    newData.ExpireOn          = req.body.ExpireOn;
    newData.Data_Unknown = req.body.Data_Unknown;

    newData.populate('userSch').save(function(err){ // <--- The line

        if (err)
                res.send(err);

        res.json({message: "data created successfully"});
    });
}); 

With that code, i can CRUD Users or Products, but it won't populate my Productlist in My User schema.

Upvotes: 3

Views: 2878

Answers (1)

robertklep
robertklep

Reputation: 203304

You have to understand that .populate() is only useful during queries, not during saving/updating/creating. So your second example isn't doing anything useful:

newData.populate('userSch').save(...)

In order to populate the Productlist entry of a user, you first need a prodSch document.

Say that you have an existing user and you want to add a product to their product list. You first create the product, and save it:

let product = new prodSch(req.body); 

product.save(function(err, product) { ...

Then, you want to add it to the product list of an existing user, which we will identify by, say, a variable called userId.

We first find the user:

userSch.findById(userId, function(err, user) { ...

Then we add the product to their product list:

user.Productlist.push(product);

Then we save the user:

user.save(function(err, user) { ...

Everything combined (leaving out error and existence checking for brevity, but make sure to add that yourself!):

let product = new prodSch(req.body); 

product.save(function(err, product) {
  userSch.findById(userId, function(err, user) {
    user.Productlist.push(product);
    user.save(function(err, user) {
      ...done...
    });
  });
});

Instead of findById/push/save, you can possibly also use findByIdAndUpdate:

product.save(function(err, product) {
  userSch.findByIdAndUpdate(userId, {
    $push : { Productlist : product._id }
  }, {
    new   : true // return the updated document, if you want
  }, function(err, user) {
    ...done...
  });
});

Then, to query a user and populate the list of products that they have:

userSch.findById(userId).populate('Productlist').exec(function(err, user) {
  ...
});

It is worthwhile to read and fully understand the documentation on population: http://mongoosejs.com/docs/populate.html

Upvotes: 1

Related Questions