Automattic / Automattic/mongoose

Nested, empty objects are not saved on type Mixed or Object

Open
#8,505 7 comments 7 reactions 0 assignees View on GitHub
backwards-breaking
Dominant language
JavaScript
Stars
27.5k
Forks
4k
Avg merge
2d 7h
Merged PRs (30d)
35

Description

**Do you want to request a *feature* or report a *bug*?**
Bug

**What is the current behavior?**
Attempts to save nested, empty objects in a field of type `Mixed` are futile; The empty object is not saved.

**If the current behavior is a bug, please provide the steps to reproduce.**

```
const mongoose = require('mongoose');
const util = require('util');

mongoose.connect('mongodb://localhost/test', {useNewUrlParser: true});

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));

db.once('open', function() {
const mainSchema = new mongoose.Schema({
nested: {
type: mongoose.Schema.Types.Mixed,
required: true,
},
}, {strict: false});

const Main = mongoose.model('Main', mainSchema);

const mainInstance = new Main({
nested: {
a: [
1,
2,
{},
{
a: {
anyOtherProp: '', // <-- Try commenting this line out
b: {},
},
},
],
},
});

console.debug('mainInstance: ', util.inspect(mainInstance, false, null, true ));
/* ^^Result:
{
_id: 5e1d6959890dec46d573dab2,
nested: {
a: [
1,
2,
{},
{
a: {
anyOtherProp: ''
}
}
]
}
}
*/

mainInstance.save(function (err, saved) {
if (err) return console.error(err);
console.debug('saved: ', util.inspect(saved, false, null, true ));
/* ^^Result:
{
_id: 5e1d6959890dec46d573dab2,
nested: {
a: [
1,
2,
{},
{
a: {
anyOtherProp: ''
}
}
]
},
__v: 0
}
*/

Main.find(function (err, instances) {
if (err) return console.error(err);
console.debug('instances: ', util.inspect(instances, false, null, true )) // Result is same as previous
})
});
});
```

Please notice that the nested property `b` is missing in the example above. In my case, the object I am trying to save is dynamic and so it is not possible to define a recursive schema.

**What is the expected behavior?**
I expect the all nested objects, be they empty or filled, to be recursively saved on type `Mixed` or equivalent types.

~I have had limited success when recursively iterating all nested objects and calling the `markModified` method. However, if the field with the type `Mixed` has the `required` property set to true, the required validation is also applied to all nested fields, and so fields with type null are marked as invalid.~

Even recursively marking all properties as modified doesn't result in the empty, nested objects being saved.

**What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.**
```
"mongo: "4.2.2",
"mongoose": "5.8.7",
"node": "10.16.0"
```

Contributor guide

Open the contributing guide

Research direction

Start with the provided JavaScript reproduction, focusing on the Mixed schema field, mainInstance.save(), and the subsequent Main.find() call. Verify how nested empty objects are handled during persistence, then confirm that all nested objects in the example, including b, are saved without requiring a recursive schema.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, mongodb, node.js
Domain
backend, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.