Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to restrict mongoose default value whose not present in database during find()

I have the following schema.

var UserSchema = new mongoose.Schema({
  username: {
    type: String,
    unique: true,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  test: {
    type: String, 
    default: 'hello world'
  }
});

UserSchema.pre('save', function(callback) {
  var user = this;
  this.test = undefined; // here unset test field which prevent to add in db 
});

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

But when I find data for example

User.find(function(err, users) {
    if (err)
      res.send(err);

    res.json(users);
  });

it always returns

[
    {
        _id: "56fa6c15a9383e7c0f2e4477",
        username: "abca",
        password: "$2a$05$GkssfHjoZnX8na/QMe79LOwutun1bv2o76gTQsIThnjOTW.sobD/2",
        __v: 0,
        test: "hello world"
    }
]

How can I modify or add any special param to get data without test field and without any change in query, let's say

User.find({}, '-test', function (err, users){

});

also, I have set the default value in model: test: "hello world" but I do not want this value to appear in the response. I have also set this.test = undefined; and this should mean that it is preventing this default value to be added into database, however I am still getting this in response.

like image 420
waqas jamil Avatar asked Mar 29 '16 12:03

waqas jamil


2 Answers

Set your schema as

test: {
    type: String, 
    default: 'hello world',
    select: false
}

Check the SchemaType#select in the document.

like image 176
hankchiutw Avatar answered Nov 12 '22 09:11

hankchiutw


  1. You want the test property persisted in database and just don't want it selected when querying:

You can use select in a pre find hook:

UserSchema.pre('find', function (next) {
    this.select({ test: false });
    next();
});

In a query hook (as opposed to a save hook for example), this refers to your query object. In a save hook it refers to the current document being saved.

This hook will only execute for find queries, not findById or findOne queries.

OR

(see Hank Chiu's answer)

set the select flag to false in the schema :

test: {
      type: String, 
      default: 'hello world',
      select: false,
}
  1. You don't want the testproperty persisted in database :

Remove the test property from schema and add a test virtual :

schema.virtual('test').get(function () {
    return 'hello world';
});

user.test will return hello world.

  1. You want the test property persisted in database but return something different :

Add a getter your test definition :

test: {
    type: String, 
    default: 'hello world',
    get: function () {
        return 'hello guys';
    }
}

user.test will return hello guys but its true value will be persisted in database.

Old erroneous answer :

You can use select which takes an object of Model properties as keys and booleans as values :

User
    .find({})
    .select({
        test: false;
    })
    .exec(function (err, users) {
        // users won't have the test property
    });

like image 34
Komo Avatar answered Nov 12 '22 09:11

Komo