3

I am new to mongodb and come from relational database, and without join it's kind pain for me to go on with mongodb.

What i want to archive here is getting all the projects and update the projectType with proper project type name rather with project type id. Somehow the projects.attrubtes just can't be overwrite. then i tried the following post. with no luck. any help is appreciated. anyone can give me some guide would be much appreciated.

Why can't you modify the data returned by a Mongoose Query (ex: findById)

var _ = require('lodash');
var project = require('./project.model');
var Form = require('../form/form.model');

// Get list of projects
exports.index = function(req, res) {
  project.find(function (err, projects) {
    if(err) { return handleError(res, err); }

    _.each(projects, function(element, index){
      Form.findOne({_id : projects[index].projectType}, '-formContent -_id -createdDateTime', function(error, form){

        if(form !== undefined) projects[index].projectType = form.formName;
      });
    });

    return res.json(200, projects);
  }).sort({ createdDateTime: 'desc' });
};
Community
  • 1
  • 1
Bill
  • 17,872
  • 19
  • 83
  • 131

1 Answers1

3

Mongoose documents don't allow adding properties. You need to either call the lean() method before exec() as documents returned from queries with the lean option enabled are plain javascript objects or cast the returned document to a plain object:.

From the docs:

project.find().lean().exec(function (err, projects) {
    projects[0] instanceof mongoose.Document // false
});

So your code should look like:

project.find()
    .lean()
    .exec(function (err, projects) {
        if(err) { return handleError(res, err); }

        _.each(projects, function(element, index){
            Form.findOne(
                {_id : projects[index].projectType}, 
                '-formContent -_id -createdDateTime', 
                function(error, form){
                    if(form !== undefined) projects[index].projectType = form.formName;
                }
            );
        });

        return res.json(200, projects);
    }).sort({ createdDateTime: 'desc' });

or cast the returned document to a plain object:

project.find()
    .exec(function (err, docs) {
        if(err) return res.send(err);
        var projects = [];
        _.each(docs, function(item, i) {
            var obj = item.toObject();
            Form.findOne(
                {_id : docs[i].projectType}, /* {_id : item.projectType} */
                '-formContent -_id -createdDateTime', 
                function(error, form){
                    if(form !== undefined) {
                        obj.projectType = form.formName;
                        projects.push(obj);
                    }
                }
            );
        });

        res.send(projects); 
    });
chridam
  • 100,957
  • 23
  • 236
  • 235
  • Awesome answer i figure out myself but this is even better, was just about to post my own answer, but this is way better! – Bill Jun 29 '15 at 08:00
  • Again thank you very much for the detailed answer, hail! – Bill Jun 29 '15 at 08:01
  • @bluebill1049 No worries, glad to be of help. I had to modify the second approach since it had some errors. – chridam Jun 29 '15 at 08:09