Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose query: remove "_id" attribute, keep virtual attribute "id" in results

I am running an Express.js app, and I have the following setup:

models.js

var schemaOptions = {
    toJSON: {
      virtuals: true
    },
    toObject: {
        virtuals: true
    }
};

var modelSchema = new mongoose.Schema({
    name     : { type: String, required: true }

}, schemaOptions);

modelSchema.virtual('id').get(function() { return this._id; });

controllers.js

exports.getModel = function(req, res) {
    Model.find().select('name').exec(function(err,model) {
        if (err) {
            return res.status(500).json({errors:err, message: 'Internal server error'});
        }
        return res.status(200).json({model: model});
    });
};

The result of the above query would be something like:

{ "_id":"dakjdjkakda", "name":"MontyPython", "id":"dakjdjkakda" } 

because of the Virtual attribute I defined in the modelSchema.

If I change the query select statement to:

Model.find().select('-_id name').exec(function(err,model) {}

The result would be:

{"name":"MontyPython", "id":null }

I believe this happens because the Virtual attribute points to the _id attribute.

My question is, how can remove the _id attribute in the query, but keep the id alias I created?

like image 249
Claudiu S Avatar asked Feb 17 '15 17:02

Claudiu S


4 Answers

If you are using mongoose,

You can handle in when toJSON, you can decide how it display but you can't mention it in your query.

Model.find().select('name').exec(function(err,model) {}

 new mongoose.Schema(yourSchema, {
    toJSON: { 
       transform: function(doc, ret) {
         ret.id = ret._id;
         delete ret._id;
       }
     }
   );}
like image 115
Thomas Lee Avatar answered Oct 08 '22 10:10

Thomas Lee


You might use global approach. Try this one out:

mongoose.plugin((schema) => {
  schema.options.toJSON = {
    virtuals: true,
    versionKey: false,
    transform(doc, ret) {
      ret.id = ret._id;
      delete ret._id;
    }
  };
});
like image 37
kboom Avatar answered Oct 08 '22 10:10

kboom


You cannot do that. MongoDB requires _id attribute to be present as per documentation.

Your option is to use virtual attribute as in your example and perhaps $project to hide the field in the query result.

Otherwise, your mongo driver, such as Mongoose, should be able to hide or rename the desired field or attribute.

like image 25
makumo Avatar answered Oct 08 '22 11:10

makumo


You can add virtual field id like this as you got it right in your code:

modelSchema.virtual('id').get(function () {

    return this._id;
});

and then remove the actual _id using toJSON's transform option:

modelSchema.set('toJSON', {
    virtuals: true,
    transform: function(doc, ret) {
        delete ret._id;
    }
});

Setting virtuals: true will make sure that your virtual field, i.e. id will be serialized.

like image 42
Babak Avatar answered Oct 08 '22 09:10

Babak