Reputation: 31
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
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