Improve support for partially denormalized subdocs, including populating denormalized subdocs
See original GitHub issueDo you want to request a feature or report a bug? Request a feature
What is the current behavior?
When a schema is set as strict
, it is not possible to append different fields to the model OR save those fields in the database.
When a schema is set as not strict
, it is possible to append different fields AND save those fields in the database
What is the proposed behavior?
It would be nice if these two features could be split into two distinct features/flags. I have a use case where I would like to append/set additional properties to a model, and have this returned to the client when using toJSON
, but I don’t want these fields to be saved to the database.
Currently, this doesn’t seem possible unless I disable strict for the schema altogether, and create a manual pre-save hook to clean up data that I don’t want when saving. Needless to say this adds overhead and is prone to bugs if new fields are added.
Use case
The main use case is being able to populate denormalised data easily, which currently is not possible if using strict
schemas.
For example:
//Bar model, has a name property and some other properties that we are interested in
const BarSchema = new Schema({
name: String,
more: String,
another: Number,
})
mongoose.model('Bar', BarSchema)
//Denormalised Bar schema with just the name, for use on the Foo model
const BarNameSchema = new Schema({
_id: {
type: Schema.Types.ObjectId,
ref: 'Bar',
},
name: String,
})
//Foo model, which contains denormalized bar data (just the name
const FooSchema = new Schema({
something: String,
other: Number,
bar: BarNameSchema,
})
mongoose.model('Foo', FooSchema)
//Now for some routes I want to be able to load the full `Bar` model, and set it on the `bar` property of a loaded `foo` document
const _id = ...
const foo = mongoose.model('Foo').findOne({_id})
const bar = mongoose.model('Bar').findOne({foo.bar._id})
//This won't work, mongoose will drop the additional properties because the schema is set to `strict`
foo.bar = bar
//I could make the schema not-strict, but then saving foo will save redundant properties in the database
await foo.save() //don't want the full bar data to be saved on the model
So ideally, these two behaviours of strict
could be separated somehow into a separate flag/setting. However, I am also open to other suggestions that would solve our problem.
To be honest this has been a pet peeve of mine for a few years of working with Mongoose now. It’s so easy to populate data, and it’s so easy to make and manage denormalized data in your database, but it seems the combination of the two still causes unnecessary friction.
Maybe there’s a use case for defining a new schema type, which is a “Denormalized” type, which can refer to another model and which will store a select number of fields alongside the parent document, but which can also easily be populated with additional fields for output as JSON/object, while not saving those fields in the database. 🤔
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:11 (7 by maintainers)
This does make sense. I’m thinking the syntax will look like this:
So if you put a
ref
on a single nested subdoc, Mongoose will be smart enough to replacebar
with a populated doc if you callpopulate('bar')
.The tricky part is what happens if you overwrite certain properties of
bar
? For example, ifbar
is populated, what shoulddoc.bar.name = 'new name'; await doc.save();
do? Should it just setdoc.bar.name
, should it update bothdoc.bar.name
and the populated doc’sname
?@vkarpov15 I think I can confirm that all cases are working now, thanks! 👍🏼