Closed mhombach closed 3 years ago
This is something worth discussing more. Currently, this is by design. The spirit of this behavior is to apply defaults where possible, because setDefaultsOnInsert
isn't always on. This way, you can use defaults to avoid an extra != null
check if you want to use String#startsWith()
or similar.
You can always use Document#$isDefault()
to check whether age
is set to the default value or not.
@vkarpov15 i kinda agree that it's more writing when you need to null-check attributes and can't rely on it beeing an empty string or so.
But the thing that made me create this issue is the pure fact, that "reading" a mongoose-document should, if no custom hooks are modifying it, return the object "as it is" from the database. The intent on pulling some document from the database is to know the values that are stored in the database. If there is an attribute that is undefined
there will always be a reason why that value is saved as undefined
into the database. In my opinion one should start rethinking there and not letting the database set "some value the nest time the data is pulled from the db".
Scenario:
undefined
because at the time these entried were created first, there was no username as default.undefined
then it was imported and not created the normal way.
But if you now find
a document and the correct undefined
gets replaced by the currently logged in user, then the document incorrectly states, that user xyz has created that document, which is simply not true.
I am not saying that this behaviour MUST not be used, but i too would like to discuss this and maybe we can work out some option/setting for that behaviour like setting forceDefault: true/false
or forceDefaultOnEmpty: true/false
in the schema :)Any updates on this issue? We sometimes deliberately put empty objects to the database and count on them to be empty when we fetch them. But they are populated with the default values.
@GirayEryilmaz you can use Document#$isDefault()
to check if a value is set using a default.
We'll add a new option to disable defaults on queries, since we already have a defaults
option for documents in https://github.com/Automattic/mongoose/commit/9609e87418b97064adc98bcaa47f85a09d899c06 and #8271
TLDR; Model.findOne().setOptions({ defaults: false })
should skip applying defaults to the result document. See the changes from https://github.com/Automattic/mongoose/commit/9609e87418b97064adc98bcaa47f85a09d899c06 to learn about the defaults
option for the Model()
constructor.
Hello,
The default behaviour may be helpful for values like booleans. But for other kind of values like creation date, ids etc., it's not a desired behaviour. Especially if the default option is "setDefaultsOnInsert" only.
I think the default behaviour should be reversed. And we should be able to fill in defaults on demand when reading. If this change involves an annoying breaking change, i suggest adding an option on schema like :
uuid: {
type: String,
default: () => uuid(),
setDefaultOnRead: false,
},
@hugomallet I don't understand your issue, can you please clarify?
@vkarpov15, my case was :
I added a new field scheduledAt to an existing model. This fields defaults to the current date at the time of the insert if not defined. Something like this :
scheduledAt: {
type: Date,
default: () => new Date(),
},
My issue is that the previous objects have an undefined scheduledAt field. But when i read, scheduledAt equals to the current date (read time) which is an unwanted value because it changes at every read. I expected to have undefined instead of an incorrect value.
@hugomallet you can create a middleware that sets defaults
to false
for all find and findOne operations:
schema.pre(['find', 'findOne'], function disableDefaults() {
this.setOptions({ defaults: false });
});
Would that help?
Hi, @vkarpov15 Thanks for adding defaults
as a model constructor option!
In addition to Model.findOne().setOptions({ defaults: false })
Is it possible to also have defaultsOnRead: false
added as a schema options property?
@hugomallet you can create a middleware that sets
defaults
tofalse
for all find and findOne operations:schema.pre(['find', 'findOne'], function disableDefaults() { this.setOptions({ defaults: false }); });
Would that help?
Doesn't seems to work on me. Thoughts? I have the exact same issue as hugomallet
@junjenfong please open a new issue and follow the issue template. "Doesn't work" isn't an actionable bug report.
Do you want to request a feature or report a bug?
Possible bug or unexpected behaviour
What is the current behavior?
.find()
overwrites fields that areundefined
but have adefault
value with that exact value, making it inconsistent and not possible to see if such that value is set in the database or not. See #7269 for reference.If the current behavior is a bug, please provide the steps to reproduce.
What is the expected behavior? The default value of an attribute should be used on creation or maybe even on
update
(https://mongoosejs.com/docs/defaults.html#the-setdefaultsoninsert-option) but NOT on pure reading a document from the database.Please mention your node.js, mongoose and MongoDB version. node v8.11.3, mongoose 5.3.13, mongoDB latest version