将created_at和updated_at字段添加到mongoose模式

cho*_*ovy 148 mongoose mongodb node.js express

有没有办法将created_at和updated_at字段添加到mongoose模式,而不必在每次调用新的MyModel()时都传递它们?

created_at字段将是一个日期,仅在创建文档时添加.每当在文档上调用save()时,updated_at字段将使用新日期进行更新.

我在我的架构中尝试了这个,但除非我明确地添加它,否则该字段不会显示:

var ItemSchema = new Schema({
    name    : { type: String, required: true, trim: true }
  , created_at    : { type: Date, required: true, default: Date.now }
});
Run Code Online (Sandbox Code Playgroud)

Pav*_*lov 244

更新:(5年后)

注意:如果您决定使用Kappa架构(事件采购+ CQRS),则根本不需要更新日期.由于您的数据是一个不可变的仅附加事件日志,因此您只需要事件创建日期.类似于Lambda架构,如下所述.然后,您的应用程序状态是事件日志(派生数据)的投影.如果您收到有关现有实体的后续事件,则您将使用该事件的创建日期作为您实体的更新日期.这是微服务系统中常用的(通常被误解的)实践.

更新:(4年后)

如果您使用ObjectId您的_id字段(通常是这种情况),那么您需要做的就是:

let document = {
  updatedAt: new Date(),
}
Run Code Online (Sandbox Code Playgroud)

请查看下面的原始答案,了解如何从_id字段中获取创建的时间戳.如果您需要使用外部系统的ID,请查看Roman Rhrn Nesterov的答案.

更新:(2.5年后)

您现在可以使用#timestamps选项和mongoose版本> = 4.0.

let ItemSchema = new Schema({
  name: { type: String, required: true, trim: true }
},
{
  timestamps: true
});
Run Code Online (Sandbox Code Playgroud)

如果设置时间戳,mongoose为模式分配createdAt和updatedAt字段,则分配的类型为Date.

您还可以指定timestamp fileds的名称:

timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
Run Code Online (Sandbox Code Playgroud)

注意:如果您正在处理包含关键数据的大型应用程序,则应重新考虑更新文档.我建议你使用不可变的,仅附加数据(lambda体系结构).这意味着您只允许插入.不应该允许更新和删除!如果您想"删除"某条记录,您可以轻松地使用某些timestamp/ 字段插入新版本的文档,version 然后将deleted字段设置为true.类似地,如果要更新文档 - 您创建一个新文档,更新相应的字段并复制其余字段.然后,为了查询此文档,您将获得具有最新时间戳或最高版本的文档.不是"已删除"(该deleted字段未定义或为false).

数据不变性确保您的数据可调试 - 您可以跟踪每个文档的历史记录.如果出现问题,您还可以回滚到文档的先前版本.如果您使用这样的架构ObjectId.getTimestamp()就是您所需要的,并且它不依赖于Mongoose.


原始答案:

如果您使用ObjectId作为您的标识字段,则不需要created_at字段.ObjectIds有一个名为的方法getTimestamp().

ObjectId("507c7f79bcf86cd7994f6c0e").getTimestamp()

这将返回以下输出:

ISODate("2012-10-15T21:26:17Z")

更多信息在这里如何从Mongo ObjectID中提取创建的日期

要添加updated_at文件,您需要使用此:

var ArticleSchema = new Schema({
  updated_at: { type: Date }
  // rest of the fields go here
});

ArticleSchema.pre('save', function(next) {
  this.updated_at = Date.now();
  next();
});
Run Code Online (Sandbox Code Playgroud)

  • 这是值得了解的,即使它不是使用的解决方案,非常有趣! (5认同)
  • 你是如何在Mongoose/node.js中做到的? (3认同)
  • 我很欣赏最初的答案,但是提倡使用lambda架构听起来像是解决5x级元问题的好方法,可能永远不会提供而不是构建CRUD应用程序并保持简单,除非这种方法的复杂性是真正有道理的.请记住,你发布的是MongoDB,它几乎没有"开始"扩展,你提倡每次写入的新记录,这将很快以任何有意义的规模杀死Mongo.将其移至Cassandra部分...... (3认同)

cho*_*ovy 132

这就是我最终做的事情:

var ItemSchema = new Schema({
    name    : { type: String, required: true, trim: true }
  , created_at    : { type: Date }
  , updated_at    : { type: Date }
});


ItemSchema.pre('save', function(next){
  now = new Date();
  this.updated_at = now;
  if ( !this.created_at ) {
    this.created_at = now;
  }
  next();
});
Run Code Online (Sandbox Code Playgroud)

  • 只想指出如果你使用ObjectId然后你可以从那里获得created_at ....你不需要一个单独的字段.看看`getTimestamp()` (13认同)
  • 1.将当前时间存储在本地var中并分配它而不是每次调用new Date()时,这将确保在第一次传递created_at和updated_at时具有相同的excect值.2.新日期=>新日期() (8认同)
  • created_at的其他选项可能是将模型更改为 - > created_at:{type:Date,default:Date.now}, (6认同)
  • 也尽可能使用`Date.now()`而不是`new Date`,因为它是一个静态方法 (2认同)

mco*_*eau 105

使用timestampsSchema 的内置选项.

var ItemSchema = new Schema({
    name: { type: String, required: true, trim: true }
},
{
    timestamps: true
});
Run Code Online (Sandbox Code Playgroud)

这将自动为您的架构添加createdAt和updatedAt字段.

http://mongoosejs.com/docs/guide.html#timestamps

  • 需要猫鼬版本 >= 4.0 (2认同)
  • 我发现文档不清楚 - 这会添加字段,但它是否也确保它们在每次更新时都会更新? (2认同)

Bin*_*les 73

从Mongoose 4.0开始,您现在可以在Schema上设置一个时间戳选项,让Mongoose为您处理:

var thingSchema = new Schema({..}, { timestamps: true });
Run Code Online (Sandbox Code Playgroud)

您可以更改所用字段的名称,如下所示:

var thingSchema = new Schema({..}, { timestamps: { createdAt: 'created_at' } });
Run Code Online (Sandbox Code Playgroud)

http://mongoosejs.com/docs/guide.html#timestamps

  • 同意,这是猫鼬 4.0 中的最佳选择。 (3认同)
  • 似乎是最好的解决方案imo.Upvoted. (2认同)

Rom*_*rov 29

如果使用update()或findOneAndUpdate()

有{upsert: true}选项

您可以使用 $setOnInsert

var update = {
  updatedAt: new Date(),
  $setOnInsert: {
    createdAt: new Date()
  }
};
Run Code Online (Sandbox Code Playgroud)


Pha*_*inh 24

添加timestamps到您的Schema喜欢然后createdAt,updatedAt将自动为您生成

var UserSchema = new Schema({
    email: String,
    views: { type: Number, default: 0 },
    status: Boolean
}, { timestamps: {} });
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述
你也可以改变createdAt -> created_at的

timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
Run Code Online (Sandbox Code Playgroud)


Kav*_*eri 17

在你的model:

const User = Schema(
  {
    firstName: { type: String, required: true },
    lastName: { type: String, required: true },
    password: { type: String, required: true }
  },
  {
    timestamps: true
  }
);
Run Code Online (Sandbox Code Playgroud)

之后你的model内容collection将是这样的:

{
    "_id" : ObjectId("5fca632621100c230ce1fb4b"),
    "firstName" : "first",
    "lastName" : "last",
    "password" : "$2a$15$Btns/B28lYIlSIcgEKl9eOjxOnRjJdTaU6U2vP8jrn3DOAyvT.6xm",
    "createdAt" : ISODate("2020-12-04T16:26:14.585Z"),
    "updatedAt" : ISODate("2020-12-04T16:26:14.585Z"),
}
Run Code Online (Sandbox Code Playgroud)


aam*_*rya 15

对于带有 Mongoose 的 NestJs,请使用这个

@Schema({timestamps: true})
Run Code Online (Sandbox Code Playgroud)


rOO*_*b85 8

这就是我创建和更新的方式.

在我的架构中,我添加了创建和更新,如下所示:

   /**
     * Article Schema
     */
    var ArticleSchema = new Schema({
        created: {
            type: Date,
            default: Date.now
        },
        updated: {
            type: Date,
            default: Date.now
        },
        title: {
            type: String,
            default: '',
            trim: true,
            required: 'Title cannot be blank'
        },
        content: {
            type: String,
            default: '',
            trim: true
        },
        user: {
            type: Schema.ObjectId,
            ref: 'User'
        }
    });

然后在文章控制器里面的文章更新方法我添加了:

/**
     * Update a article
     */
    exports.update = function(req, res) {
        var article = req.article;

        article = _.extend(article, req.body);
        article.set("updated", Date.now());

        article.save(function(err) {
            if (err) {
                return res.status(400).send({
                    message: errorHandler.getErrorMessage(err)
                });
            } else {
                res.json(article);
            }
        });
    };

粗体部分是感兴趣的部分.


Nik*_*y_R 7

var ItemSchema = new Schema({
    name : { type: String, required: true, trim: true }
});

ItemSchema.set('timestamps', true); // this will add createdAt and updatedAt timestamps
Run Code Online (Sandbox Code Playgroud)

文件:https://mongoosejs.com/docs/guide.html#timestamps


小智 6

在您的模型架构中,只需添加一个属性timestamps并为其分配值true,如下所示:-

var ItemSchema = new Schema({
   name :  { type: String, required: true, trim: true },
},{timestamps : true}
);
Run Code Online (Sandbox Code Playgroud)


M.R*_*ari 6

如果您使用 Nestjs 和 @Schema 装饰器,您可以实现如下目的:

@Schema({
  timestamps: true,
})
Run Code Online (Sandbox Code Playgroud)

时间戳选项告诉猫鼬将createdAt和updatedAt字段分配给您的模式。分配的类型是日期。

默认情况下,字段名称为createdAt 和updatedAt。

通过设置timestamps.createdAt和timestamps.updatedAt自定义字段名称。


Joh*_*yHK 5

您可以使用timestamp的插件mongoose-troop将此行为添加到任何架构中。


Sha*_*Roy 5

我们也可以通过使用模式插件来实现这一点。

在helpers/schemaPlugin.js文件中

module.exports = function(schema) {

  var updateDate = function(next){
    var self = this;
    self.updated_at = new Date();
    if ( !self.created_at ) {
      self.created_at = now;
    }
    next()
  };
  // update date for bellow 4 methods
  schema.pre('save', updateDate)
    .pre('update', updateDate)
    .pre('findOneAndUpdate', updateDate)
    .pre('findByIdAndUpdate', updateDate);
};
Run Code Online (Sandbox Code Playgroud)

并在models/ItemSchema.js文件中:

var mongoose = require('mongoose'),
  Schema   = mongoose.Schema,
  SchemaPlugin = require('../helpers/schemaPlugin');

var ItemSchema = new Schema({
  name    : { type: String, required: true, trim: true },
  created_at    : { type: Date },
  updated_at    : { type: Date }
});
ItemSchema.plugin(SchemaPlugin);
module.exports = mongoose.model('Item', ItemSchema);
Run Code Online (Sandbox Code Playgroud)