Skip to content

Commit 61179b4

Browse files
authored
Merge pull request #14972 from Automattic/vkarpov15/gh-14944
docs(documents): add section on setting deeply nested properties, including warning about nullish coalescing assignment
2 parents 94b2873 + e6119de commit 61179b4

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

docs/documents.md

+49
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ to documents as stored in MongoDB. Each document is an instance of its
88
<li><a href="#documents-vs-models">Documents vs Models</a></li>
99
<li><a href="#retrieving">Retrieving</a></li>
1010
<li><a href="#updating-using-save">Updating Using <code>save()</code></a></li>
11+
<li><a href="#setting-nested-properties">Setting Nested Properties</a></li>
1112
<li><a href="#updating-using-queries">Updating Using Queries</a></li>
1213
<li><a href="#validating">Validating</a></li>
1314
<li><a href="#overwriting">Overwriting</a></li>
@@ -81,6 +82,54 @@ doc.name = 'foo';
8182
await doc.save(); // Throws DocumentNotFoundError
8283
```
8384

85+
## Setting Nested Properties
86+
87+
Mongoose documents have a `set()` function that you can use to safely set deeply nested properties.
88+
89+
```javascript
90+
const schema = new Schema({
91+
nested: {
92+
subdoc: new Schema({
93+
name: String
94+
})
95+
}
96+
});
97+
const TestModel = mongoose.model('Test', schema);
98+
99+
const doc = new TestModel();
100+
doc.set('nested.subdoc.name', 'John Smith');
101+
doc.nested.subdoc.name; // 'John Smith'
102+
```
103+
104+
Mongoose documents also have a `get()` function that lets you safely read deeply nested properties. `get()` lets you avoid having to explicitly check for nullish values, similar to JavaScript's [optional chaining operator `?.`](https://masteringjs.io/tutorials/fundamentals/optional-chaining-array).
105+
106+
```javascript
107+
const doc2 = new TestModel();
108+
109+
doc2.get('nested.subdoc.name'); // undefined
110+
doc2.nested?.subdoc?.name; // undefined
111+
112+
doc2.set('nested.subdoc.name', 'Will Smith');
113+
doc2.get('nested.subdoc.name'); // 'Will Smith'
114+
```
115+
116+
You can use optional chaining `?.` and nullish coalescing `??` with Mongoose documents.
117+
However, be careful when using [nullish coalescing assignments `??=`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_assignment) to create nested paths with Mongoose documents.
118+
119+
```javascript
120+
// The following works fine
121+
const doc3 = new TestModel();
122+
doc3.nested.subdoc ??= {};
123+
doc3.nested.subdoc.name = 'John Smythe';
124+
125+
// The following does **NOT** work.
126+
// Do not use the following pattern with Mongoose documents.
127+
const doc4 = new TestModel();
128+
(doc4.nested.subdoc ??= {}).name = 'Charlie Smith';
129+
doc.nested.subdoc; // Empty object
130+
doc.nested.subdoc.name; // undefined.
131+
```
132+
84133
## Updating Using Queries {#updating-using-queries}
85134
86135
The [`save()`](api/model.html#model_Model-save) function is generally the right

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
"lint": "eslint .",
9393
"lint-js": "eslint . --ext .js --ext .cjs",
9494
"lint-ts": "eslint . --ext .ts",
95-
"lint-md": "markdownlint-cli2 \"**/*.md\"",
95+
"lint-md": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#benchmarks\"",
9696
"build-browser": "(rm ./dist/* || true) && node ./scripts/build-browser.js",
9797
"prepublishOnly": "npm run build-browser",
9898
"release": "git pull && git push origin master --tags && npm publish",

0 commit comments

Comments
 (0)