Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FindOne returns default value of the nonexistent filed. #4362

Closed
efkan opened this issue Jul 23, 2016 · 3 comments
Closed

FindOne returns default value of the nonexistent filed. #4362

efkan opened this issue Jul 23, 2016 · 3 comments

Comments

@efkan
Copy link
Contributor

efkan commented Jul 23, 2016

First: A workaround to overcome this issue:
Model.findOne({id: 'blabla'}).select('email password createdAt').lean().exec()

issue:

I use an createdAt field -which has an expires (TTL 24h) and a default (Date.now) value- in my Users model to store the creating date info of the new created users.

If the user activates the account the system removes the createdAt field.
If the user doesn't activate the account the system remove the account from Users collection after 24 hours.

In my authentication operations, I check the existing of createdAt field firstly.
If the user is not activated I show a message like Account is not activated.

When I try FindOne method for purpose of the above authentication procedure, I get Date.now value although there is no a createdAt field in the document because of the user has activated his account.

createdAt field in my User model:
createdAt: { type: Date, expires: '24h', default: Date.now },

My method:
Users.findOne({email: username}, 'email, password, createdAt', function(err, user) {

By using the above method createdAt value returns at every time.

ps: i searched the issue but i couldn't anything.

@vkarpov15
Copy link
Collaborator

That's just how defaults work, when there isn't a createdAt field in the doc mongoose will add one. If you only want to add createdAt when creating a new doc:

schema.pre('save', function(next) {
  if (this.isNew) {
    this.createdAt = Date.now();
  }
  next();
});

Also, I wouldn't recommend separating the fields in your projection Users.findOne({email: username}, 'email, password, createdAt' /** <-- remove commas here */) with commas.

@viktornord
Copy link

viktornord commented May 7, 2018

Stumbled upon the same problem.
@vkarpov15 it should not work that way. Although default value is set on saving it is misleading to set it when find the document, because it should actually return exact data stored in DB, isn't it? I would vote for reopening the issue.

@vkarpov15
Copy link
Collaborator

Not necessarily, mongoose has a lot of places where the document doesn't represent the exact data stored in the db: getters, virtuals, etc. Either way, we assert on this behavior and changing it would break a lot of people's code, so we won't change it unless there's a lot of demand to change it. Here's a workaround:

createdAt: {
  type: Date,
  default: function() {
    if (this.isNew) { return new Date(); }
    return undefined;
  }
}

This will make it so that createdAt is only set when saving to the database, but it'll be undefined if you loaded a doc from the db and createdAt isn't set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants