How to exclude some fields from the document

JavascriptMongodbExpressMongoose

Javascript Problem Overview


I have the following simple shema:

 var userSchema = new Schema({
    name : String,
   age: Number,
   _creator: Schema.ObjectId
  });

  var User = mongoose.model('User',userSchema);

What I want to do is create the new document and return to client, but I want to exclude the 'creator' field from one:

app.post('/example.json', function (req, res) {
   var user = new User({name: 'John', age: 45, _creator: 'some ObjectId'});
   user.save(function (err) {
      if (err) throw err;

      res.json(200, {user: user});     // how to exclude the _creator field?
   });
});

At the end I want to send the new created user without _creator field:

{
   name: 'John',
   age: 45
} 

Is it possible to make without extra find request to mongoose?

P.S:It's preferable to make it by

Javascript Solutions


Solution 1 - Javascript

Another way to handle this on the schema level is to override toJSON for the model.

UserSchema.methods.toJSON = function() {
  var obj = this.toObject()
  delete obj.passwordHash
  return obj
}

I came across this question looking for a way to exclude password hash from the json i served to the client, and select: false broke my verifyPassword function because it didn't retrieve the value from the database at all.

Solution 2 - Javascript

The documented way is

UserSchema.set('toJSON', {
	transform: function(doc, ret, options) {
		delete ret.password;
		return ret;
	}
});

UPDATE - You might want to use a white list:

UserSchema.set('toJSON', {
	transform: function(doc, ret, options) {
		var retJson = {
			email: ret.email,
			registered: ret.registered,
			modified: ret.modified
		};
		return retJson;
	}
});

Solution 3 - Javascript

Come across your question when I was trying to find a similar answer with pymongo. It turns out that in mongo shell, with the find() function call, you can pass a second parameter which specifies how the result document looks like. When you pass a dictionary with attribute's value being 0, you are excluding this field in all the document that come out of this query.

In your case, for example, the query will be like:

db.user.find({an_attr: a_value}, {_creator: 0});

It will exclude _creator parameter for you.

In pymongo, the find() function is pretty much the same. Not sure how it translate to mongoose though. I think it's a better solution compare to manually delete the fields afterwards.

Hope it helps.

Solution 4 - Javascript

I would use the lodash utilities _.pick() or _.omit()

var _ = require('lodash');

app.post('/example.json', function (req, res) {
    var user = new User({name: 'John', age: 45, _creator: 'some ObjectId'});
    user.save(function (err) {
        if (err) throw err;
        // Only get name and age properties
        var userFiltered = _.pick(user.toObject(), ['name', 'age']);
        res.json(200, {user: user});
    });
});

The other example would be:

var _ = require('lodash');

app.post('/example.json', function (req, res) {
    var user = new User({name: 'John', age: 45, _creator: 'some ObjectId'});
    user.save(function (err) {
        if (err) throw err;
        // Remove _creator property
        var userFiltered = _.omit(user.toObject(), ['_creator']);
        res.json(200, {user: user});
    });
});

Solution 5 - Javascript

You can call toObject() on the document to convert it to a plain JS object that you can freely modify:

user = user.toObject();
delete user._creator;
res.json(200, {user: user});

Solution 6 - Javascript

By following the MongoDB documentation, you can exclude fields by passing a second parameter to your query like:

User.find({_id: req.user.id}, {password: 0})
        .then(users => {
          res.status(STATUS_OK).json(users);
        })
        .catch(error => res.status(STATUS_NOT_FOUND).json({error: error}));

In this case, password will be excluded from the query.

font: https://docs.mongodb.com/v2.8/tutorial/project-fields-from-query-results/#return-all-but-the-excluded-field

Solution 7 - Javascript

I am using Mongoosemask and am very happy with it.

It does support hiding and exposing properties with other names based on your need

https://github.com/mccormicka/mongoosemask

var maskedModel = mongomask.mask(model, ['name', 'age']); //And you are done.

Solution 8 - Javascript

You can do this on the schema file itself.

// user.js
var userSchema = new Schema({
    name : String,
    age: Number,
   _creator: Schema.ObjectId
  });

userSchema.statics.toClientObject = function (user) {
  const userObject = user?.toObject();
  // Include fields that you want to send
  const clientObject = {
    name: userObject.name,
    age: userObject.age,
  };

  return clientObject;
};

var User = mongoose.model('User',userSchema);

Now, in the controller method where you are responding back to the client, do the following

return res.json({
    user: User.toClientObject(YOUR_ENTIRE_USER_DOC),
  });

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionErikView Question on Stackoverflow
Solution 1 - JavascriptCharlesView Answer on Stackoverflow
Solution 2 - JavascriptXerriView Answer on Stackoverflow
Solution 3 - JavascriptRexView Answer on Stackoverflow
Solution 4 - JavascriptfernandopasikView Answer on Stackoverflow
Solution 5 - JavascriptJohnnyHKView Answer on Stackoverflow
Solution 6 - JavascriptLeo RibeiroView Answer on Stackoverflow
Solution 7 - JavascriptfinoView Answer on Stackoverflow
Solution 8 - JavascriptdpacmanView Answer on Stackoverflow