ARHAM RUMI
ARHAM RUMI

Reputation: 543

Mongoose model saves default date as that of last time the server was started at

I have this mongoose model

const reportUsSchema = new mongoose.Schema({
  texts: [
    {
      text: { type: String, default: "" },
      date_time: { type: Date, default: new Date() },
    },
  ],
});

I want this:

Whenever a new text is pushed in the texts field I want to insert the current datetime.

What I am getting (Problem):

I am getting the same date time when I restarted the server last time. For example if I have restarted the server 2 days ago I am getting the 2 days before date, which is wrong.

What I have tried:

  1. Using moment.js: I have tried multiple combinations of moment.js too. Adding them here:
date_time: { type: Date, default: moment() }

And

date_time: { type: Date, default: moment().format() }

And

date_time: { type: Date, default: moment().utc(true) }

And

date_time: { type: Date, default: moment().utc(true).format() }
  1. Using the built-in Date()

I am using it currently in the above code but none of above worked for me.

Note: The thing that worked is instead of depending upon this default value from the mongoose model, I have passed the current datetime value alongwith the text. And this is working well.

I could not understand the behavior. Help me understand where I was wrong.

Mongoose version: 5.10.7

Edit

I know new schema thing. I want to know what I am doing wrong that mongoose is behaving like this. I want to understand this behavior.

Upvotes: -1

Views: 459

Answers (3)

Karandeep Singh
Karandeep Singh

Reputation: 1

When the file is compiled on deployment, new Date() gets also invoked which returns a time stamp of that moment when the server was started, thus here on default value looks like text: { type: String, default: "2025-02-05T06:54:52.374Z" } which is static.

now we need to make it dynamic for that we have to figure out a way to invoke new Date(), whenever something is saved this can be achieved by either of the two ways below.

const reportUsSchema = new mongoose.Schema({
  texts: [
    {
      text: { type: String, default: () => { return new Date() } },
      date_time: { type: Date, default: new Date() },
    },
  ],
});

//OR

const reportUsSchema = new mongoose.Schema({
  texts: [
    {
      text: { type: String, default: Date.now},
    },
  ],
});

Upvotes: 0

jQueeny
jQueeny

Reputation: 8291

Based on your comment from this answer you need to update your schema to use Date.now instead of new Date() like this:

const reportUsSchema = new mongoose.Schema({
  texts: [
    {
      text: { type: String, default: "" },
      date_time: { type: Date, default: Date.now }, //< This change
    },
  ],
});

This is because when you use default: new Date() you are telling the schema to use a default date at the time the schema was defined, not the document. So if you deploy your app to a server and then start up your app the default value for that field in that schema will be the time your app started.

However, if you use Date.now then mongoose knows to set the default to use the datetime at the time of document creation.

In the mongoose docs they do recommend this: updated: { type: Date, default: Date.now }, in their kitchen sink example. They also list it here in their Default Functions example.

In summary, when you use new Date() you called the function so use the return value. If you use Date.now you pass the function (Date.now()) so call it at document creation time.

Upvotes: 0

Khải Hồ Quang
Khải Hồ Quang

Reputation: 70

The default: new Date() option in the schema means that the date_time field will have a default value of the current date and time when the document is created or when the field is not specified.

You can use the timestamps option:

let ItemSchema = new Schema({
  texts: [
    {
      text: { type: String, default: "" },
    },
  ],
},
{
  timestamps: true
});

You can also specify the timestamp fileds:

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

Upvotes: 2

Related Questions