简体   繁体   中英

Node.js, MongDB (Mongoose) - Adding to data retrieved.

I currently have the following code:

User.find({ featuredMerchant: true })
.lean()
.limit(2)
.exec(function(err, users) {
    if (err) {
        console.log(err);
        return res.status(400).send({
            message: errorHandler.getErrorMessage(err)
        });
    } else {
        _.forEach(users, function(user){
            _.forEach(user.userListings, function(listing){
                Listing.find({
                    user: user
                }).populate('listings', 'displayName merchantName userImageName hasUploadedImage').exec(function(err, listings){
                    user.listings = listings;
                });
            });
        });
        res.jsonp(users); 
    } 
});

As you can see I am trying to add the retrieved listings to each 'user' in the 'users' lean object that I have returned. If I do a console.log(user) inside the Listing.find exec method after adding 'user.listings = listings', the result is as I would expect; a user object with a listings property, with this listing property containing all the listings retrieved.

However, if I console.log the 'users' object, the listings for each user cannot be found.

I'm pretty sure I'm doing something stupid here, but I really cannot work out what. Any help would be greatly appreciated. Thank you!

you right about stupid thing !

No offense, I think this is a common mistake :)

_.forEach(users, function(user){
    _.forEach(user.userListings, function(listing){
        Listing.find({
            user: user
        })
        .populate('listings', 'displayName merchantName userImageName hasUploadedImage')
        .exec(function(err, listings){
            user.listings = listings;
        });
     });
});
// Listing.find inside foreach hasn't finish yet
// I suppose it's always an asynchronous call
res.jsonp(users);

Maybe you can fix it using promises. This an example with q library.

var promises = [];
_.forEach(users, function(user){
    _.forEach(user.userListings, function(listing){
        var deferred = q.defer();
        promises.push(deferred);
        Listing.find({
            user: user
        })
        .populate('listings', 'displayName merchantName userImageName hasUploadedImage')
        .exec(function(err, listings){
            user.listings = listings;
            deferred.resolve(user);
        });
     });
});

q
    .all(promises)
    .done(function(allUsers){
        // Do what you want here with your users
        res.jsonp(allUsers);    
    });

Check this and don't hesitate to fix it because I can't test it.

Thank you both for your input. It's truly appreciated. I managed to solve this an easier way which now I come to think of it is pretty obvious - but hey we live and learn. Basically, my 'userListings' model field was an array of Object Id's and I wanted to add the physical listings from the listings model into the data returned. The following code did the trick for me.

exports.findFeaturedMerchants = function(req, res, next) {

User.find({ featuredMerchant: true })
.populate('userListings')
.limit(2)
.exec(function(err, data) {
    _.forEach(data, function(user){
        Listing.populate(user.userListings, '', function(err, user){
            if (err) {
                console.log(err);
                return res.status(400).send({
                    message: errorHandler.getErrorMessage(err)
                });
            }
        });
    });
    console.log(data);
    res.jsonp(data); 
});
};

I simply had to populate each userListings object into the user, by using the populate function twice - once for the user and another time for each listing. I was finding it tricky to get my head around - probably because I didn't understand how the populate function worked exactly, but there we go :)

Jamie

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM