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

mongoose find
mongoose default value not saved
mongoose limit
mongoose query builder
mongoose findone example
mongoose find sort
mongoose schema find
mongoose operators

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.

Set your schema as

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

Check the SchemaType#select in the document.

How to restrict mongoose default value whose not present , GitHub is home to over 50 million developers working together to mongoose default value whose not present in database during find() #4024. Default functions and this; Declaring defaults in your schema. Your schemas can define default values for certain paths. If you create a new document without that path set, the default will kick in. Note: Mongoose only applies a default if the value of the path is strictly undefined.

  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
    });

Mongoose v5.9.20: Validation, Validation; Built-in Validators; The unique Option is Not a Validator; Custom Mongoose registers validation as a pre('save') hook on every schema by default. required: true } }); var Cat = db.model('Cat', schema); // This cat has no name the SchemaType's checkRequired() function to determine if the value satisfies the​  The Eq("item", BsonNull.Value) query using the FilterDefinitionBuilder.Eq() method matches documents that either contain the item field whose value is null or that do not contain the item field. The { item => undef } query matches documents that either contain the item field whose value is null or that do not contain the item field.

Use select function as your example it would be like

User.find(/* condition */).select('username -_id -__v')

The above code will return the username field only

TL: DR

Fields are written as a single string with whitespace separator, to exclude field add - prefix like -_id or -username.

Mongoose v5.9.20:, If not set, defaults to this.model If obj is present, it is cast instead of this query. The .cursor() function triggers pre find hooks, but not post find hooks. This function calls the MongoDB driver's Collection#deleteMany() function. «​Boolean» If true, delete any properties whose value is undefined when casting an update. An integer that specifies the exclusive upper limit of the sequence. Can be any valid expression that resolves to an integer. <non-zero step> Optional. An integer that specifies the increment value. Can be any valid expression that resolves to a non-zero integer. Defaults to 1.

Introduction to Mongoose for MongoDB, Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. of these documents can vary as it is not enforced like SQL databases. While Mongo is schema-less, SQL defines a schema via the table definition. default values, validators, etc., whereas a Mongoose model provides an  If i replace {packId: packId }, with a static value {packId: '55083c370e5fcc8e1ea7984c' }, it works. i precise i'm on the good database, packid is a objectId and when i do the querry in mogo, it works. But i saw a difference in the mongoose/lib/model.js : if i console.log(conditions) at the end of Model.find function i 've got

Creating and Saving a record with MongoDB, When I went through them for the certification months ago, things went but never paid attention to when I was actually logged into Glitch or not In the myApp.js file, the createAndSavePerson() function outline should be there waiting for Connect to the database using `mongoose.connect(<Your URI>)`  Let's say we wanted to create the default animal to be saved if we don't supply. 0:05. any data to the model. 0:08. Mongooses schema lets us as defined default values very easily. 0:13. Let's change the schema to give us a goldfish animal as default. 0:24. Instead of just specifying a type, 0:26. we can give each property a type and a default

db.collection.updateOne(), Updates a single document within the collection based on the filter. The same query selectors as in the find() method are available. If the collation is unspecified but the collection has a default collation (see db. If no collation is specified for the collection or for the operations, MongoDB uses the simple binary​  This post is part of a series called An Introduction to Mongoose for MongoDB and Node.js. Bulk Import a CSV File Into MongoDB Using Mongoose With Node.js Mongoose is a JavaScript framework that is commonly used in a Node.js application with a MongoDB database.

Comments
  • Thank you for answer, Can I define "select" on conditional basis ?
  • What do you mean "on conditional basis"? Once select:false defined, you can retrieve the attribute by using select('+test') when query.
  • I have multiple roles like student, instructor, studio . So, what can I do to make "select" true for student and false for instructor?
  • You can use function in default attribute, ex. default: function(){ return (this.role=='student') ? 'hello world':'';}. But this will not work if you are going to store different values in the field test.
  • Chui , I understand your logic but problem is if role is "student" then default value become 'hello world' when role become "instructor" or else it's become '' (empty string ) still test field save in db . When I find any roles lets say "Instructor " field become visible for example "test: ' ' "
  • That is exactly the same as what '-test' does. So that's not what the OP is asking. They want the field exluded "automatically" so that every .find() call already excludes the field without having to do '-test' or .select({ "test": false }) or .select({ "test": -1 }) ( which is again the same thing )
  • Oh you're right. I missed the "without any change in query" part, my bad. I updated my answer
  • Probably should note that middleware like this is pretty specific. So you would need findOne as well or else a .findOne() or .findById() would "still" return the field. I also wonder if considering the OP does not want to "store" the data if "virtuals" would be a better choice, and then excluding them from serialization. That can be done as well.
  • I agree, there's many ways to exclude a field from query results, but it all comes down to what the OP needs. I think that a find middleware makes sense if he wants to exclude fields from a generic query to make the results lighter. If he's querying a specific user, I think he's more likely to want to include all fields. I edited my answer based on your comment.
  • You might want to lookup discriminators for that : mongoosejs.com/docs/discriminators.html. It will allow you to define models that inherits from another schema. This way you can define an admin schema that inherits from user schema.