добавить поля create_at и updated_at в схемы mongoose

105

Есть ли способ добавить поля created_at и updated_at в схему mongoose, без необходимости передавать их каждый раз, когда вызывается новый MyModel()?

Поле created_at будет датой и будет добавляться только при создании документа. Поле updated_at будет обновляться с новой датой, когда в документе вызывается функция save().

Я пробовал это в своей схеме, но поле не отображается, если я его не добавлю:

var ItemSchema = new Schema({
    name    : { type: String, required: true, trim: true }
  , created_at    : { type: Date, required: true, default: Date.now }
});
  • 0
    Я сделал именно то, что вы сделали, и это сработало. Использование Mongoose 4.8.4. Может быть, новая вещь?
  • 1
    это было довольно давно.
Показать ещё 1 комментарий
Теги:
express
mongoose

16 ответов

12
Лучший ответ

Если используется update() или findOneAndUpdate()

с опцией {upsert: true}

вы можете использовать $setOnInsert

var update = {
  updatedAt: new Date(),
  $setOnInsert: {
    createdAt: new Date()
  }
};
  • 2
    Красиво и элегантно
  • 1
    это работает в большинстве библиотек Монго. переход к принятому ответу
Показать ещё 3 комментария
164

ОБНОВЛЕНИЕ: (4 года спустя)

Если вы используете ObjectId в качестве поля _id (как правило, это так), все, что вам нужно сделать, это:

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

Проверьте мой первоначальный ответ ниже, как получить созданную метку времени из поля _id. Если вам нужно использовать идентификаторы из внешней системы, ответьте на запрос Романа Ррнна Нестерова.

ОБНОВЛЕНИЕ: (2,5 года спустя)

Теперь вы можете использовать параметр #timestamps с версией mongoose >= 4.0.

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

Если установлены метки времени, mongoose присваивает вашим строкам поля createdAt и updatedAt, назначенный тип Date.

Вы также можете указать имена имен меток:

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

Примечание.. Если вы работаете над большим приложением с критическими данными, вы должны пересмотреть обновление своих документов. Я бы посоветовал вам работать с неизменяемыми, доступными только для приложения данными (лямбда-архитектура). Это означает, что что вы только разрешаете вставки. Обновления и удаления не должны быть разрешено! Если вы хотите "удалить" запись, вы можете легко вставьте новую версию документа с помощью timestamp/versionи затем установите для поля deleted значение true. Аналогично, если вы хотите для обновления документа - вы создаете новый с соответствующим поля обновлены, а остальные поля скопированы. Затем, чтобы запросите этот документ, вы получите тот, у которого установлена ​​самая новая отметка времени или самая высокая версия, которая не "удалена" (поле deleted undefined или false`).

Непрерывность данных гарантирует, что ваши данные отлаживаются - вы можете отслеживать история каждого документа. Вы также можете откат к предыдущему версию документа, если что-то пойдет не так. Если вы идете с таким архитектура ObjectId.getTimestamp() - это все, что вам нужно, и это не Зависит от Мангуста.


ОРИГИНАЛЬНЫЙ ОТВЕТ:

Если вы используете 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();
});
  • 3
    Как вы делаете это в Mongoose / node.js?
  • 5
    Это стоит знать, даже если это не решение, которое привыкает, очень интересно!
Показать ещё 10 комментариев
120

Вот что я сделал:

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();
});
  • 8
    1. Сохраните текущее время в локальной переменной и присвойте его вместо того, чтобы каждый раз вызывать new Date (), это обеспечит, чтобы при первом проходе create_at и updated_at имели одно и то же значение исключения. 2. новая дата => новая дата ()
  • 13
    Хотелось бы отметить, что если вы используете ObjectId, вы можете получить оттуда selected_at .... вам не нужно отдельное поле. Проверьте getTimestamp()
Показать ещё 6 комментариев
89

Используйте встроенную опцию timestamps для вашей схемы.

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

Это автоматически добавит поля createdAt и updatedAt к вашей схеме.

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

  • 1
    Требуется версия mongoose> = 4.0
  • 2
    Я нахожу документы неясными - это добавляет поля, но также гарантирует, что они обновляются при каждом обновлении?
Показать ещё 3 комментария
59

Начиная с Mongoose 4.0 теперь вы можете установить параметр timestamps на Схеме, чтобы Mongoose справился с этим для вас:

var thingSchema = new Schema({..}, { timestamps: true });

Вы можете изменить имя полей, используемых так:

var thingSchema = new Schema({..}, { timestamps: { createdAt: 'created_at' } });

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

  • 2
    Похоже, лучшее решение IMO. Upvoted.
  • 1
    Согласитесь, это лучший вариант в Mongoose 4.0.
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);
            }
        });
    };

Облачные области представляют интерес.

4

Добавьте timestamps к вашему Schema, как это, тогда createdAt и updatedAt автоматически сгенерируют для вас

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

Изображение 4668
Также вы можете изменить createdAt -> created_at на

timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
  • 5
    Это должен быть принятый ответ
  • 1
    Теперь, когда Mongoose делает всю эту работу за вас, я согласен, что сейчас это лучшее решение.
4

Вы можете использовать плагин timestamp mongoose-troop, чтобы добавить это поведение в любую схему.

2

Вы можете легко использовать этот плагин. Из документов:

var timestamps = require('mongoose-timestamp');
var UserSchema = new Schema({
    username: String
});
UserSchema.plugin(timestamps);
mongoose.model('User', UserSchema);
var User = mongoose.model('User', UserSchema)

И также задайте имя полей, если хотите:

mongoose.plugin(timestamps,  {
  createdAt: 'created_at', 
  updatedAt: 'updated_at'
});
0

Использовать 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-мира.

0

Я действительно делаю это в спине

Если все будет хорошо с обновлением:

 // All ifs passed successfully. Moving on the Model.save
    Model.lastUpdated = Date.now(); // <------ Now!
    Model.save(function (err, result) {
      if (err) {
        return res.status(500).json({
          title: 'An error occured',
          error: err
        });
      }
      res.status(200).json({
        message: 'Model Updated',
        obj: result
      });
    });
0

Моя версия мангуста - 4.10.2

Кажется, что работает только hook findOneAndUpdate

ModelSchema.pre('findOneAndUpdate', function(next) {
  // console.log('pre findOneAndUpdate ....')
  this.update({},{ $set: { updatedAt: new Date() } });
  next()
})
0
const mongoose = require('mongoose');
const config = require('config');
const util = require('util');

const Schema = mongoose.Schema;
const BaseSchema = function(obj, options) {
  if (typeof(options) == 'undefined') {
    options = {};
  }
  if (typeof(options['timestamps']) == 'undefined') {
    options['timestamps'] = true;
  }

  Schema.apply(this, [obj, options]);
};
util.inherits(BaseSchema, Schema);

var testSchema = new BaseSchema({
  jsonObject: { type: Object }
  , stringVar : { type: String }
});

Теперь вы можете использовать это, так что нет необходимости включать эту опцию в каждую таблицу

0

мы можем достичь этого, используя плагин схемы.

В 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);
0

Используйте функцию для возврата вычисленного значения по умолчанию:

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

ItemSchema.pre('save', function(done) {
  this.updated_at = Date.now();
  done();
});
  • 0
    не нужно оборачивать Date.now() в функцию, просто сделайте: ...default: Date.now()
  • 1
    Я обертываю его в функцию, чтобы в тестах можно было смоделировать «.now ()». В противном случае он запускается только один раз во время инициализации, и значение не может быть легко изменено.
Показать ещё 3 комментария
-4

Вы можете использовать middleware и virtuals. Ниже приведен пример вашего поля updated_at:

ItemSchema.virtual('name').set(function (name) {
  this.updated_at = Date.now;
  return name;
});
  • 0
    Когда это на самом деле будет установлено? и будет ли оно сохраняться? Таким образом, через 3 дня у него все еще будет дата 3 дня назад?
  • 0
    виртуальный будет вызываться всякий раз, когда вы меняете данное свойство, в данном случае это name . И да, это должно быть постоянным.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню