using mongoose .populate()

Black Sulfur
Black Sulfur used Ask the Experts™
on
I am used to php/mysql where I would just join tables but mongoose seems to be a whole other beast.

I have a product schema and a user schema.

here is product:

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

const productSchema = new Schema({
    title: {
        type: String,
        required: true
    },
    category: {
        type: String,
        required: true
    },
    image: {
        type: String,
        required: true
    },
    description: {
        type: String,
        required: true
    },
    userId: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    address: {
        city: {type: String, required: true }
    },
    createdAt: {
        type: Date,
        default: Date.now
    },
});

module.exports = mongoose.model('Product', productSchema);

Open in new window


And the user:

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

const userSchema = new Schema({
    firstName: {
        type: String,
        required: true
    },
    lastName:  {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true,
        index: true,
        unique: true
    },
    contactNo: {
        type: String,
        required: true
    },
    password:  {
        type: String,
        required: true
    },
    address: {
        city: {type: String, required: true },
    }
});

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

Open in new window


When I as the admin user want to see the users first name and last name for the added product (as well as that product informatioN) I would to 'join' the 'tables' and based on the UserID in the product schema get the first name and last name from the users schema.

I am trying to use .populate here but not sure if it's correct or efficient.

exports.getApprove = (req, res, next) => {
    const productId = req.params.productId;
    Product.findById(productId)
    .populate('userId', 'firstName', 'lastName')
    .then(product => {
        res.render('account/approve', {
            pageTitle: 'Approve Listing',
            path: '/accounts/approve',
            product: product
        });
    })
    .catch(err => {
        console.log(err);
    });
};

Open in new window


console.log(product.userId.firstName);

Open in new window


Just wondering if I am not meant to use .exec() or .execPopulate() here
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Distinguished Expert 2017

Commented:
Cfdo not ave mongodb experience, but a quick glance at https://www.sitepoint.com/using-joins-in-mongodb-nosql-databases/
Suggests like in other db's there does not seem to be a userid. Refereñce in your users table on whose basis in other DBs you would join table records.rt

Or product.userid to users._id as .....


With lack of exposure, I do not see an ID column in either table explicitly defined.

Author

Commented:
Hi Arnold, sorry for late reply. I my products table I have created a reference to the user:

    userId: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },

Open in new window


And then I am using populate() to basically do the join. It is working but I see in the documentation they have exec() and that was more what I was asking. Is that necessary? Why is it necessary etc.
Distinguished Expert 2017

Commented:
Unfortunately, I do not have any experience with this mongodb could you provide the documentation reference that raised this question?
Potentially, the reference you saw/referred deals with using $lookup operator that preceded the populate() option.

https://mongoosejs.com/docs/populate.html

Perhaps the data aggregation process.....

Author

Commented:
Hi Arnold,

Here is the link:

https://mongoosejs.com/docs/populate.html

And I took a screenshot too:

populate.png
Distinguished Expert 2017
Commented:
The example you posted has two ways to achieve the same result
the first seems to build and then exec the function.

the second example, defines what it is looking for and in the next steps, implicitly runs/execs the function.

you seem to have a working/functional approach.

You could create another aproach using exec function, execpopulate and then use debug (https://stackoverflow.com/questions/9910551/how-can-i-view-the-execution-plan-of-a-mongoose-js-query) on each approach to determine whose performance is better....

i can offer no such insight.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial