I have observed a very strange behavior while using the following schema:
var saleSchema = new Schema ({
...
date: {type: Date, 'default': Date.now, index: true}
...
})
When I create a new document with the aforementioned schema the date that is placed in the database is always the same and corresponds to the start time of the current process.
It feels like when indexed the now function is called when the schema is created and reused for every newly created documents.
Is this something that makes sense?
I solved for now by removing the indexing on that field, but that means that research by date will be fairly slow.
Thank You
Hmm the below script gives me the correct result:
var assert = require('assert');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/gh3675');
mongoose.set('debug', true);
var Schema = mongoose.Schema;
var saleSchema = new Schema ({
date: {type: Date, 'default': Date.now, index: true}
});
var Sale = mongoose.model('Sale', saleSchema);
console.log(new Sale().date);
setTimeout(function() {
console.log(new Sale().date);
process.exit(0);
}, 2000);
$ node gh-3675.js
Tue Dec 15 2015 09:57:23 GMT-0500 (EST)
Mongoose: sales.ensureIndex({ date: 1 }) { background: true }
Tue Dec 15 2015 09:57:25 GMT-0500 (EST)
Can you see if you can modify the provided script to reproduce your issue?
Issue's gone stale, closing.
I ran into this problem. Be sure you're not using Date.now(), as that assigns a default value to the model instead of Date.now which causes the function to run each time.
I believe I'm also getting this for { type: Date, default: new Date() }
. Using Mongoose version 4.13.12
Did anyone figure out what might have been causing this? Thanks.
@bgSosh
Instead of
{ type: Date, default: new Date() }
try
{ type: Date, default: () => { return new Date() } }
With this change, each time you create a new doc, the default function will be called and a new Date will be returned as the default.
As @brycelund pointed out, the schemaType default
property can hold either a value or a function. If a value is set as the default, ie, the return of new Date()
or Date.now()
, then each subsequent doc created from this schema will receive the exact same default value that was set when the Schema was compiled into a model.
Alternatively, if the default is a function, like Date.now
( no parens means we're setting the default property to the function Date.now itself ) or () => { return 'xyz' }
, then each doc will receive a new value from calling that function as it's default.
Here's an example that explicitly tests for the difference in behavior between passing a value and passing a function as the value for a schemaType default property:
In the following example, note that both the value passed into the schemaSame.d.default and the value returned from the schemaDiff.d.default function are computed in exactly the same way.
#!/usr/bin/env node
'use strict';
const assert = require('assert');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/test', { useMongoClient: true });
const conn = mongoose.connection;
const Schema = mongoose.Schema;
const schemaSame = new Schema({
d: {
type: Date,
default: Date.now() + Math.floor(Math.random() * 500000) // value
}
});
const schemaDiff = new Schema({
d: {
type: Date,
default: () => { return Date.now() + Math.floor(Math.random() * 500000);} // function
}
});
const Same = mongoose.model('same', schemaSame);
const Diff = mongoose.model('diff', schemaDiff);
const sames = [new Same(), new Same(), new Same()];
const diffs = [new Diff(), new Diff(), new Diff()];
async function run() {
assert.strictEqual(mongoose.version, '4.13.12');
await conn.dropDatabase();
await Same.create(sames);
await Diff.create(diffs);
// docs created from schemaSame all get the exact
// same default Date.
let s = await Same.find();
let s1 = s[0].d.toString();
let s2 = s[1].d.toString();
let s3 = s[2].d.toString();
assert.strictEqual(s1, s2);
assert.strictEqual(s2, s3);
// docs created from schemaDiff all get
// different default Dates.
let d = await Diff.find();
let d1 = d[0].d.toString();
let d2 = d[1].d.toString();
let d3 = d[2].d.toString();
assert.notStrictEqual(d1, d2);
assert.notStrictEqual(d2, d3);
console.log('All Assertions Pass.');
return conn.close();
}
run();
issues: ./3675.js
All Assertions Pass.
issues:
@lineus Oh that's great info, thanks so much for taking the time!
Thanks @lineus !
{default: Date.now()} will be called when the model has loaded means when service started.
change this to {default: Date.now} so when a new model will be created Date.now function will be called. and it will create new date.
Most helpful comment
@bgSosh
TL;DR
Instead of
{ type: Date, default: new Date() }
try
{ type: Date, default: () => { return new Date() } }
With this change, each time you create a new doc, the default function will be called and a new Date will be returned as the default.
As @brycelund pointed out, the schemaType
default
property can hold either a value or a function. If a value is set as the default, ie, the return ofnew Date()
orDate.now()
, then each subsequent doc created from this schema will receive the exact same default value that was set when the Schema was compiled into a model.Alternatively, if the default is a function, like
Date.now
( no parens means we're setting the default property to the function Date.now itself ) or() => { return 'xyz' }
, then each doc will receive a new value from calling that function as it's default.Here's an example that explicitly tests for the difference in behavior between passing a value and passing a function as the value for a schemaType default property:
In the following example, note that both the value passed into the schemaSame.d.default and the value returned from the schemaDiff.d.default function are computed in exactly the same way.
3675.js
Output: