[Node.js] 將created_at和updated_at字段添加到貓鼬模式


Answers

更新: (5年後)

注意:如果您決定使用Kappa ArchitectureEvent Sourcing + CQRS ),那麼您根本不需要更新日期。 由於您的數據是不可變的,僅附加事件日誌,因此您只需要事件創建日期。 與Lambda架構類似,如下所述。 那麼你的應用程序狀態就是事件日誌(派生數據)的投影。 如果您收到有關現有實體的後續事件,那麼您將使用該事件的創建日期作為實體的更新日期。 這是微服務系統中常用(並且常被誤解)的做法。

更新: (4年後)

如果你使用ObjectId作為你的_id字段(通常是這種情況),那麼你所需要做的就是:

let document = {
  updatedAt: new Date(),
}

請查看我的原始答案,以了解如何從_id字段獲取創建的時間戳。 如果您需要使用外部系統的ID,請檢查Roman Rhrn Nesterov的答案。

更新: (2.5年後)

您現在可以使用貓鼬版本> = 4.0的#timestamps選項。

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

如果設置時間戳,貓鼬將updatedAtupdatedAt字段分配給您的模式,分配的類型為Date

您還可以指定時間戳文件的名稱:

timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }

注意:如果您正在處理關鍵數據的大型應用程序,則應重新考慮更新文檔。 我建議你使用不可變的,僅限附加數據( lambda體系結構 )。 這意味著你只允許插入。 不應允許更新和刪除! 如果您想“刪除”一條記錄,可以使用某個timestamp / version字段輕鬆插入新版本的文檔,然後將deleted字段設置為true 。 同樣,如果你想更新一個文件 - 你創建了一個新的文件,並更新了適當的字段,並將其餘的字段複製過來。然後為了查詢這個文件,你將得到最新的時間戳或最高版本不是“刪除”( deleted字段是未定義的或假的)。

數據不可變性確保您的數據是可調試的 - 您可以跟踪每個文檔的歷史記錄。 如果出現問題,您也可以回滾到文檔的以前版本。 如果你使用這樣的體系結構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();
});
Question

有沒有一種方法可以將created_at和updated_at字段添加到貓鼬模式中,而無需在每次調用新的MyModel()時都傳遞它們?

created_at字段將是一個日期,並且僅在創建文檔時添加。 每當在文檔上調用save()時,updated_at字段將使用新日期進行更新。

我已經在我的模式中試過這個,但是除非我用expcitly添加它,否則這個字段不會顯示出來:

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



使用machinepack-datetime格式化日期時間。

tutorialSchema.virtual('createdOn').get(function () {
    const DateTime = require('machinepack-datetime');
    let timeAgoString = "";
    try {
        timeAgoString = DateTime.timeFrom({
            toWhen: DateTime.parse({
                datetime: this.createdAt
            }).execSync(),
            fromWhen: new Date().getTime()
        }).execSync();
    } catch(err) {
        console.log('error getting createdon', err);
    }
    return timeAgoString; // a second ago
});

機器包與明確的API不同,不同於一般的Javascript世界。




我的貓鼬版本是4.10.2

似乎只有鉤子findOneAndUpdate工作

ModelSchema.pre('findOneAndUpdate', function(next) {
  // console.log('pre findOneAndUpdate ....')
  this.update({},{ $set: { updatedAt: new Date() } });
  next()
})



你可以使用middlewarevirtuals 。 以下是updated_at字段的示例:

ItemSchema.virtual('name').set(function (name) {
  this.updated_at = Date.now;
  return name;
});



為您的模式使用內置timestamps選項。

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

這會自動將updatedAtupdatedAt字段添加到您的模式。

#timestamps




這就是我創建和更新所取得的成就。

在我的模式中,我添加了創建和更新,如下所示:

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

大膽的部分是感興趣的部分。




我們也可以通過使用schema插件來實現這一點。

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

並在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);



您可以使用mongoose-trooptimestamp插件將此行為添加到任何模式。