Mongoose: FindOne 返回不存在的字段的默认值。

创建于 2016-07-23  ·  3评论  ·  资料来源: Automattic/mongoose

_First:解决此问题的解决方法:_
Model.findOne({id: 'blabla'}).select('email password createdAt').lean().exec()

问题:

我在Users模型中使用了一个createdAt字段 - 它有一个 expires (TTL 24h ) 和一个默认值 ( Date.now ) 来存储创建新创建用户的日期信息。

如果用户激活帐户,系统将删除createdAt字段。
如果用户没有激活帐户,系统会在 24 小时后从Users集合中删除该帐户。

在我的身份验证操作中,我首先检查createdAt字段的存在。
如果用户未激活,我会显示类似Account is not activated.

当我为了上述身份验证过程而尝试FindOne方法时,尽管文档中没有createdAt字段,但由于用户已激活他的帐户,我得到了Date.now值.

我的User模型中的createdAt字段:
createdAt: { type: Date, expires: '24h', default: Date.now },

我的方法:
Users.findOne({email: username}, 'email, password, createdAt', function(err, user) {

通过使用上述方法createdAt每次都会返回值。

ps:我搜索了这个问题,但我什么也做不了。

最有用的评论

偶然发现了同样的问题。
@vkarpov15它不应该那样工作。 尽管在保存时设置了默认值,但在find文档时设置它会产生误导,因为它实际上应该返回存储在 DB 中的确切数据,不是吗? 我会投票支持重新打开这个问题。

所有3条评论

这就是默认值的工作方式,当文档 mongoose 中没有createdAt字段时,会添加一个。 如果您只想在创建新文档时添加createdAt

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

另外,我不建议用逗号分隔投影Users.findOne({email: username}, 'email, password, createdAt' /** <-- remove commas here */)的字段。

偶然发现了同样的问题。
@vkarpov15它不应该那样工作。 尽管在保存时设置了默认值,但在find文档时设置它会产生误导,因为它实际上应该返回存储在 DB 中的确切数据,不是吗? 我会投票支持重新打开这个问题。

不一定,mongoose 有很多地方的文档不代表存储在数据库中的确切数据:getter、virtuals 等。无论哪种方式,我们都对这种行为进行断言并更改它会破坏很多人的代码,所以除非有很多需要改变它,否则我们不会改变它。 这是一个解决方法:

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

这将让这个createdAt保存到数据库时,只能置位,但它会是undefined如果您加载从一个数据库中的文档和createdAt不放。

此页面是否有帮助?
0 / 5 - 0 等级