mongoose şemalarına create_at ve updated_at alanları ekle


166

Yeni MyModel () çağrıldığında bunları geçirmeye gerek kalmadan, bir mongoose şemasına create_at ve updated_at alanları eklemenin bir yolu var mı?

Oluşturulan_at alanı bir tarih olur ve yalnızca belge oluşturulduğunda eklenir. Belgeye save () çağrıldığında updated_at alanı yeni bir tarihle güncellenir.

Bu benim şemasında denedim, ama ben açıkça eklemek sürece alan görünmüyor:

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

Tam olarak ne yaptığını yaptım ve işe yaradı. Mongoose Kullanımı 4.8.4. Yeni bir şey olabilir mi?
martinedwards

1
bu oldukça kısa bir süre önceydi.
chovy

Evet, yukarıdakilerin şimdi işe yaradığını belirtmeye değer olduğunu düşündüm.
martinedwards

Yanıtlar:


132

Mongoose 4.0'dan itibaren, Mongoose'un bunu sizin için halletmesini sağlamak için Şema'da bir zaman damgası seçeneği ayarlayabilirsiniz:

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

Aşağıdaki gibi kullanılan alanların adını değiştirebilirsiniz:

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

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


2
Kabul etti, bu Mongoose 4.0 en iyi seçenektir.
Tadd Giles

258

GÜNCELLEME: (5 yıl sonra)

Not: Kappa Mimarisini ( Olay Kaynağı + CQRS ) kullanmaya karar verirseniz , güncellenmiş tarihe ihtiyacınız yoktur. Verileriniz değiştirilemez, salt eklenmiş bir olay günlüğü olduğundan, yalnızca olayın oluşturulma tarihine ihtiyacınız vardır. Aşağıda açıklanan Lambda Mimarisine benzer . O zaman uygulama durumunuz olay günlüğünün (türetilmiş veriler) bir projeksiyonudur. Mevcut varlık hakkında daha sonra bir etkinlik alırsanız, o etkinliğin oluşturulma tarihini kuruluşunuz için güncellenmiş tarih olarak kullanırsınız. Bu, fare hizmet sistemlerinde yaygın olarak kullanılan (ve genellikle yanlış anlaşılan) bir uygulamadır.

GÜNCELLEME: (4 yıl sonra)

ObjectIdAlanınız olarak kullanırsanız _id(genellikle durum budur), yapmanız gereken tek şey:

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

Oluşturulan zaman damgasını _idalandan nasıl alacağımla ilgili aşağıdaki orijinal yanıtımı kontrol edin . Harici sistemden kimlik kullanmanız gerekiyorsa, Roman Rhrn Nesterov'un cevabını kontrol edin.

GÜNCELLEME: (2.5 yıl sonra)

Artık #timestamps seçeneğini mongoose sürüm> = 4.0 ile kullanabilirsiniz.

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

Zaman damgaları ayarlanırsa, mongoose şemanıza alanlar createdAtve updatedAtalanlar atar , atanan türdür Date.

Ayrıca zaman damgası dosyalarının adlarını da belirtebilirsiniz:

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

Not: Kritik verileri olan büyük bir uygulama üzerinde çalışıyorsanız, belgelerinizi güncellemeyi tekrar düşünmelisiniz. Değişmez, sadece ekli verilerle ( lambda mimarisi ) çalışmanızı tavsiye ederim . Bunun anlamı, yalnızca kesici uçlara izin vermenizdir. Güncelleme ve silme işlemlerine izin verilmemelidir! Bir kaydı "silmek" istiyorsanız, belgenin bir kısmını timestamp/ version dosyalanmış olan yeni bir sürümünü kolayca ekleyebilir ve daha sonra bir deletedalan ayarlayabilirsiniz true. Benzer şekilde, bir belgeyi güncellemek istiyorsanız - uygun alanların güncellendiği ve geri kalan alanların kopyalandığı yeni bir belge oluşturursunuz.Ardından bu belgeyi sorgulamak için en yeni zaman damgasına veya "silinmedi" (deleted alan tanımsız veya yanlış`).

Veri değişmezliği, verilerinizin hata ayıklanabilmesini sağlar - her belgenin geçmişini izleyebilirsiniz. Bir şeyler ters giderse belgenin önceki sürümüne de geri dönebilirsiniz. Eğer böyle bir mimariye sahip ObjectId.getTimestamp()olursanız, ihtiyacınız olan tek şey budur ve Mongoose'a bağımlı değildir.


ORİJİNAL CEVAP:

Kimlik alanınız olarak ObjectId kullanıyorsanız alana ihtiyacınız yoktur created_at. ObjectIds adlı bir yöntem var getTimestamp().

Nesne Kimliği ( "507c7f79bcf86cd7994f6c0e"). GetTimestamp ()

Bu, aşağıdaki çıktıyı döndürür:

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

Burada daha fazla bilgi Oluşturulan tarihi bir Mongo ObjectID'den nasıl ayıklayabilirim

updated_atDosya eklemek için şunu kullanmanız gerekir:

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'de bunu nasıl yaparsınız?
Zebra Tahrik Laboratuvarı

6
Kullanılmakta olan bir çözüm olmasa bile, çok ilginç!
kasıtsız

Ancak oluşturma tarihte görünümüne geçmek istiyorsanız, bunun için özel bir değişken ayarlamak veya kimliği doğru geçmek gerekir?

3
İlk cevabı takdir ediyorum ama lambda mimarisini kullanmak için savunmak, CRUD uygulamasını oluşturmak ve bu yaklaşımın karmaşıklığı gerçekten garanti edilmedikçe basit tutmaktan ziyade 5 kat meta problemi çözmek ve muhtemelen asla teslim etmek yerine harika bir yol gibi geliyor. Unutmayın, başlamak için 'zar zor' ölçeklenen MongoDB hakkında mesaj gönderiyorsunuz ve Mongo'yu herhangi bir anlamlı ölçekte hızla öldürecek her yazma için yeni bir kayıt savunuyorsunuz. Bunu Cassandra bölümüne taşıyın ...
John Culviner

1
Aslında bu cevapta verilen bilgiler sayesinde gerçek silmeler yerine yumuşak silmeler gerçekleştirmek için arka uç tasarımımı değiştirdim. Gerçekten faydalı olan daha derin bir bilgi sağlar.
Kenna

133

Sonunda bunu yaptım:

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. Geçerli saati yerel bir değişkende saklayın ve her yeni Date () çağrısı yerine onu atayın, bu, ilk geçişte create_at ve updated_at öğelerinin aynı excect değerine sahip olmasını sağlar. 2. yeni Tarih => yeni Tarih ()
Shay Erlichmen

13
Sadece ObjectId kullanırsanız o zaman create_at oradan alabilirsiniz .... ayrı bir alana gerek olmadığını işaret etmek istiyorum. ÇıkışgetTimestamp()
Xerri

6
Oluşturulan_at için diğer seçenek modeli -> oluşturulan_at olarak değiştirmek olabilir: {type: Tarih, varsayılan: Date.now},
OscarVGG

1
@ajbraus Bir şema eklentisi yapın
wlingke

2
Ayrıca statik bir yöntem olduğu için daha hızlı Date.now()yerine mümkün olan yerlerde kullanınnew Date
karlkurzer

107

Şemanız için yerleşik timestampsseçeneği kullanın .

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

Bu, şemanıza otomatik olarak ekler createdAtve updatedAtalanları ekler .

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


1
Firavun faresi sürümü gerektirir = = 4.0
Jensen

2
Belgeleri belirsiz buluyorum - bu alanları ekliyor, ancak her güncellemede de güncellendiğinden emin mi?
Ludwik

genellikle, createAt her zaman yalnızca bir kez saklanır ... nesne oluşturulduğunda. updatedAther yeni
kayıtta

1
Ben bu "2016-12-07T11: 46: 46.066Z" var .. zaman damgası biçimini açıklayabilir misiniz, nasıl zaman dilimi değiştirmek ?? mongoDB sunucusu saat dilimi almak ??
Mahesh K

@mcompeau, Cevabınız için teşekkürler! Bunun uzun bir çekim olduğunu biliyorum, ancak bu şekilde oluşturulan alanların dizin olarak kullanılabileceğini hiç hatırlıyor musunuz?
manidos

29

Kullanıyorsanız update()veyafindOneAndUpdate()

ile {upsert: true}seçeneği

kullanabilirsiniz $setOnInsert

var update = {
  updatedAt: new Date(),
  $setOnInsert: {
    createdAt: new Date()
  }
};

1
bu çoğu mongo kütüphanesinde işe yarar. kabul edilen cevaba
geçiliyor

1
Mogo'nun varsayılan _idalanını kullanıyorsanız, bir createdAtalana ihtiyacınız yoktur . Daha fazla ayrıntı için aşağıdaki cevabımı kontrol edin.
Pavel Nikolov

1
... ORİJİNAL CEVAP'ımı kontrol et .
Pavel Nikolov

25

Ekle timestampsBlogunuza Schemasonra böyle createdAtve updatedAtsizin için otomatik üretecektir

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

resim açıklamasını buraya girin
Ayrıca değiştirebilir createdAt -> created_attarafından

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

2
Mongoose tüm bu işleri sizin için yaptığını, bunun şimdi en iyi çözüm olduğunu kabul ediyorum.
Vince Bowdren

Evet, kabul et @VinceBowdren
Mr.spShuvo

8

Bu şekilde yaratmayı ve güncellemeyi başardım.

Benim şema içinde oluşturulan ve güncellenen şöyle ekledi:

   / **
     * Makale Şeması
     * /
    var ArticleSchema = yeni Şema ({
        oluşturuldu: {
            tür: Tarih,
            varsayılan: Date.now
        },
        güncellenmiş: {
            tür: Tarih,
            varsayılan: Date.now
        },
        Başlık: {
            type: String,
            varsayılan: '',
            trim: gerçek,
            gerekli: 'Başlık boş olamaz'
        },
        içerik: {
            type: String,
            varsayılan: '',
            kırpma: gerçek
        },
        kullanıcı: {
            tür: Schema.ObjectId,
            ref: 'Kullanıcı'
        }
    });

Sonra makale denetleyicisi içindeki makale güncelleme yöntemime ekledim:

/ **
     * Bir makaleyi güncelleyin
     * /
    export.update = işlev (req, res) {
        var makale = gerekli parçacık;

        article = _.extend (makale, gerekli herkes);
        article.set ("güncellendi", Date.now ());

        article.save (function (err) {
            if (err) {
                res.status (400) .send ({
                    message: errorHandler.getErrorMessage (hata)
                });
            } Başka {
                res.json (madde);
            }
        });
    };

Kalın bölümler ilgilenilen bölümlerdir.



4

Bu davranışı herhangi bir şemaya eklemek için timestampeklentisini kullanabilirsiniz mongoose-troop.


3

Bu eklentiyi çok kolay bir şekilde kullanabilirsiniz . Dokümanlardan:

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

İsterseniz alanların adını da ayarlayabilirsiniz:

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

2

bunu şema eklentisini kullanarak da başarabiliriz .

Gelen helpers/schemaPlugin.jsdosyanın

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

ve models/ItemSchema.jsdosyada:

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

2

Model şemanızda, bir özellik zaman damgaları ekleyin ve gösterildiği gibi true değeri atayın : -

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

Bu ne yapacak?
chovy

Zaman damgası özelliği, her belgeye create_at ve updated_at alanları ekleyecektir. Created_at alanı belgenin oluşturulma zamanını ve updated_at alanı ise belgenin oluşturulma zamanını varsa güncelleme zamanını gösterir. Her iki alanın değeri ISO saat biçimindedir. Umarım bu şüphelerini temizler Chovy.
Pavneet Kaur

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

Şimdi bunu kullanabilirsiniz, böylece bu seçeneği her tabloya eklemeye gerek kalmaz


1

Firavun faresi versiyonum 4.10.2

Sadece kanca findOneAndUpdateçalışıyor gibi görünüyor

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

0

Hesaplanan varsayılan değeri döndürmek için bir işlev kullanın:

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

Date.now()bir işlevi sarmaya gerek yok sadece yapmak:...default: Date.now()
karlkurzer

1
Testlerde '.now ()' alay edebilmem için bir işleve sarıyorum. Aksi takdirde, başlatma sırasında yalnızca bir kez çalışır ve değer kolayca değiştirilemez.
orourkedd

1
Bunun default: Date.now()yanlış olacağını unutmayın . Eğer bir şey varsa default: Date.now. Aksi takdirde tüm belgeleriniz aynı zaman damgasına sahip olacaktır: Başvurunuzun başladığı zaman;)
Max Truxa

default: Date.nowStratejinizi seviyorum . çok daha temiz.
orourkedd

0

Aslında bunu arkada yapıyorum

Güncelleme ile her şey yolunda giderse:

 // 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

Tarih saatini biçimlendirmek için machinepack-datetime komutunu kullanın.

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

Makine paketi, ekspres veya genel Javascript dünyasının aksine açık API ile mükemmeldir.


-2

Ara katman yazılımlarını ve sanalları kullanabilirsiniz . Alanınız için bir örnek updated_at:

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

Bu ne zaman ayarlanacak? ve devam edecek mi? Yani 3 gün sonra, hala 3 gün öncesinden bir tarih olurdu?
chovy

bu özelliği, belirli bir özelliği her değiştirdiğinizde çağrılır name. Ve evet, kalıcı olmalı.
zemirco

Bu, Item nesnesindeki tüm alanlar için çalışır mı? Bu çözümün istediğim şeyi yaptığından emin değilim
chovy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.