Skip to content

Commit e79681d

Browse files
committed
Merge branch '4.10' into 5064
Conflicts: package.json
2 parents 3d62d35 + 71d85b1 commit e79681d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2011
-514
lines changed

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ docs/
22
bin/
33
test/triage/
44
test/model.discriminator.test.js
5+
tools/
6+
test/es6/

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ benchmarks/v8.log
1010
.DS_Store
1111
docs/*.json
1212
docs/source/_docs
13-
docs/*.html
1413
tags
1514
test/triage/*.js
1615
/.idea

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ before_script:
1313
- tar -zxvf mongodb-linux-x86_64-2.6.11.tgz
1414
- mkdir -p ./data/db
1515
- ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db --syslog --port 27017
16+
script:
17+
- npm test
18+
- npm run lint

History.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,79 @@
1+
4.9.9 / 2017-05-13
2+
==================
3+
* docs: correct value for Query#regex() #5230
4+
* fix(connection): don't throw if .catch() on open() promise #5229
5+
* fix(schema): allow update with $currentDate for updatedAt to succeed #5222
6+
* fix(model): versioning doesn't fail if version key undefined #5221 [basileos](https://github.com/basileos)
7+
* fix(document): don't emit model error if callback specified for consistency with docs #5216
8+
* fix(document): handle errors in subdoc pre validate #5215
9+
10+
4.9.8 / 2017-05-07
11+
==================
12+
* docs(subdocs): rewrite subdocs guide #5217
13+
* fix(document): avoid circular JSON if error in doc array under single nested subdoc #5208
14+
* fix(document): set intermediate empty objects for deeply nested undefined paths before path itself #5206
15+
* fix(schema): throw error if first param to schema.plugin() is not a function #5201
16+
* perf(document): major speedup in validating subdocs (50x in some cases) #5191
17+
18+
4.9.7 / 2017-04-30
19+
==================
20+
* docs: fix typo #5204 [phutchins](https://github.com/phutchins)
21+
* fix(schema): ensure correct path for deeply nested schema indexes #5199
22+
* fix(schema): make remove a reserved name #5197
23+
* fix(model): handle Decimal type in insertMany correctly #5190
24+
* fix: upgrade kareem to handle async pre hooks correctly #5188
25+
* docs: add details about unique not being a validator #5179
26+
* fix(validation): handle returning a promise with isAsync: true #5171
27+
28+
4.9.6 / 2017-04-23
29+
==================
30+
* fix: update `parentArray` references when directly assigning document arrays #5192 [jhob](https://github.com/jhob)
31+
* docs: improve schematype validator docs #5178 [milesbarr](https://github.com/milesbarr)
32+
* fix(model): modify discriminator() class in place #5175
33+
* fix(model): handle bulkWrite updateMany casting #5172 [tzellman](https://github.com/tzellman)
34+
* docs(model): fix replaceOne example for bulkWrite #5168
35+
* fix(document): don't create a new array subdoc when creating schema array #5162
36+
* fix(model): merge query hooks from discriminators #5147
37+
* fix(document): add parent() function to subdocument to match array subdoc #5134
38+
39+
4.9.5 / 2017-04-16
40+
==================
41+
* fix(query): correct $pullAll casting of null #5164 [Sebmaster](https://github.com/Sebmaster)
42+
* docs: add advanced schemas docs for loadClass #5157
43+
* fix(document): handle null/undefined gracefully in applyGetters() #5143
44+
* fix(model): add resolveToObject option for mapReduce with ES6 promises #4945
45+
46+
4.9.4 / 2017-04-09
47+
==================
48+
* fix(schema): clone query middleware correctly #5153 #5141 [clozanosanchez](https://github.com/clozanosanchez)
49+
* docs(aggregate): fix typo #5142
50+
* fix(query): cast .$ update to underlying array type #5130
51+
* fix(populate): don't mutate populate result in place #5128
52+
* fix(query): handle $setOnInsert consistent with $set #5126
53+
* docs(query): add strict mode option for findOneAndUpdate #5108
54+
55+
4.9.3 / 2017-04-02
56+
==================
57+
* docs: document.js fixes for functions prepended with `$` #5131 [krmannix](https://github.com/krmannix)
58+
* fix: Avoid exception on constructor check #5129 [monkbroc](https://github.com/monkbroc)
59+
* docs(schematype): explain how to use `isAsync` with validate() #5125
60+
* docs(schematype): explain custom message with required function #5123
61+
* fix(populate): only apply refPath duplicate id optimization if not array #5114
62+
* fix(document): copy non-objects to doc when init() #5111
63+
* perf(populate): dont clone whole options every time #5103
64+
* feat(document): add isDirectSelected() to minimize isSelected() changes #5063
65+
* docs(schematypes): explain some subtleties with arrays #5059
66+
67+
4.9.2 / 2017-03-26
68+
==================
69+
* fix(discriminator): handle class names consistently #5104
70+
* fix(schema): make clone() work with reusing discriminator schemas #5098
71+
* fix(querycursor): run pre find hooks with .cursor() #5096
72+
* fix(connection): throw error if username:password includes @ or : #5091
73+
* fix(timestamps): handle overwriting createdAt+updatedAt consistently #5088
74+
* fix(document): ensure subdoc post save runs after parent save #5085
75+
* docs(model): improve update docs #5076 [bertolo1988](https://github.com/bertolo1988)
76+
177
4.9.1 / 2017-03-19
278
==================
379
* fix(query): handle $type for arrays #5080 #5079 [zoellner](https://github.com/zoellner)

docs/faq.jade

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,44 @@ block content
3030
doc.array[3] = 'changed';
3131
doc.markModified('array');
3232
doc.save();
33+
34+
hr#unique-doesnt-work
35+
:markdown
36+
**Q**. I declared a schema property as `unique` but I can still save duplicates. What gives?
37+
38+
**A**. Mongoose doesn't handle `unique` on it's own, `{ name: { type: String, unique: true } }`
39+
just a shorthand for creating a [MongoDB unique index on `name`](https://docs.mongodb.com/manual/core/index-unique/).
40+
For example, if MongoDB doesn't already have a unique index on `name`, the below code will not error despite the fact that `unique` is true.
41+
:js
42+
var schema = new mongoose.Schema({
43+
name: { type: String, unique: true }
44+
});
45+
var Model = db.model('Test', schema);
46+
47+
Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
48+
console.log(err); // No error, unless index was already built
49+
});
50+
:markdown
51+
However, if you wait for the index to build using the `Model.on('index')` event, attempts to save duplicates will correctly error.
52+
:js
53+
var schema = new mongoose.Schema({
54+
name: { type: String, unique: true }
55+
});
56+
var Model = db.model('Test', schema);
57+
58+
Model.on('index', function(err) { // <-- Wait for model's indexes to finish
59+
assert.ifError(err);
60+
Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
61+
console.log(err);
62+
});
63+
});
64+
:markdown
65+
MongoDB persists indexes, so you only need to rebuild indexes if you're starting
66+
with a fresh database or you ran `db.dropDatabase()`. In a production environment,
67+
you should [create your indexes using the MongoDB shell])(https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/)
68+
rather than relying on mongoose to do it for you. The `unique` option for schemas is
69+
convenient for development and documentation, but mongoose is *not* an index management solution.
70+
3371
hr#date_changes
3472
:markdown
3573
**Q**. Why don't in-place modifications to date objects

docs/includes/nav.jade

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ ul
2222
a(href="./schematypes.html")
2323
span schema
2424
| types
25+
li.custom-schema-types
26+
a(href="./customschematypes.html")
27+
| custom schema types
28+
li.advanced-schemas
29+
a(href="./advanced_schemas.html")
30+
| advanced usage
2531
li
2632
a(href="./models.html")
2733
| models
@@ -68,9 +74,6 @@ ul
6874
li
6975
a(href="./browser.html")
7076
| schemas in the browser
71-
li
72-
a(href="./customschematypes.html")
73-
| custom schema types
7477
li
7578
a(href="./compatibility.html")
7679
| MongoDB Version Compatibility

docs/schematypes.jade

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,33 @@ block content
231231
var Empty2 = new Schema({ any: Array });
232232
var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
233233
var Empty4 = new Schema({ any: [{}] });
234+
p
235+
| Arrays implicitly have a default value of `[]` (empty array).
236+
:js
237+
var Toy = mongoose.model('Test', ToySchema);
238+
console.log((new Toy()).toys); // []
239+
p
240+
| To overwrite this default, you need to set the default value to `undefined`
241+
:js
242+
var ToySchema = new Schema({
243+
toys: {
244+
type: [ToySchema],
245+
default: undefined
246+
}
247+
});
248+
p
249+
| If an array is marked as `required`, it must have at least one element.
250+
:js
251+
var ToySchema = new Schema({
252+
toys: {
253+
type: [ToySchema],
254+
required: true
255+
}
256+
});
257+
var Toy = mongoose.model('Toy', ToySchema);
258+
Toy.create({ toys: [] }, function(error) {
259+
console.log(error.errors['toys'].message); // Path "toys" is required.
260+
});
234261
h3#customtypes Creating Custom Types
235262
p
236263
| Mongoose can also be extended with custom SchemaTypes. Search the

docs/source/acquit.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ var files = [
3030
input: 'test/docs/validation.test.js',
3131
output: 'validation.html',
3232
title: 'Validation'
33+
},
34+
{
35+
input: 'test/docs/schemas.test.es6.js',
36+
output: 'advanced_schemas.html',
37+
title: 'Advanced Schemas'
3338
}
3439
];
3540

docs/subdocs.jade

Lines changed: 83 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,101 @@ extends layout
33
block content
44
h2 Sub Docs
55
:markdown
6-
[Sub-documents](./api.html#types-embedded-js) are docs with schemas of
7-
their own which are elements of a parent document array:
6+
Subdocuments are documents embedded in other documents. In Mongoose, this
7+
means you can nest schemas in other schemas. Mongoose has two
8+
distinct notions of subdocuments: arrays of subdocuments and single nested
9+
subdocuments.
810
:js
911
var childSchema = new Schema({ name: 'string' });
1012

1113
var parentSchema = new Schema({
12-
children: [childSchema]
13-
})
14+
// Array of subdocuments
15+
children: [childSchema],
16+
// Single nested subdocuments. Caveat: single nested subdocs only work
17+
// in mongoose >= 4.2.0
18+
child: childSchema
19+
});
1420

1521
:markdown
16-
Sub-documents enjoy all the same features as normal
17-
[documents](./api.html#document-js). The only difference is that they are
22+
Subdocuments are similar to normal documents. Nested schemas can have
23+
[middleware](http://mongoosejs.com/docs/middleware.html), [custom validation logic](http://mongoosejs.com/docs/middleware.html),
24+
virtuals, and any other feature top-level schemas can use. The major
25+
difference is that subdocuments are
1826
not saved individually, they are saved whenever their top-level parent
1927
document is saved.
2028
:js
2129
var Parent = mongoose.model('Parent', parentSchema);
2230
var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
2331
parent.children[0].name = 'Matthew';
32+
33+
// `parent.children[0].save()` is a no-op, it triggers middleware but
34+
// does **not** actually save the subdocument. You need to save the parent
35+
// doc.
2436
parent.save(callback);
2537

2638
:markdown
27-
If an error occurs in a sub-document's middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap!
39+
Subdocuments have `save` and `validate` [middleware](http://mongoosejs.com/docs/middleware.html)
40+
just like top-level documents. Calling `save()` on the parent document triggers
41+
the `save()` middleware for all its subdocuments, and the same for `validate()`
42+
middleware.
2843

2944
:js
3045
childSchema.pre('save', function (next) {
31-
if ('invalid' == this.name) return next(new Error('#sadpanda'));
46+
if ('invalid' == this.name) {
47+
return next(new Error('#sadpanda'));
48+
}
3249
next();
3350
});
3451

3552
var parent = new Parent({ children: [{ name: 'invalid' }] });
3653
parent.save(function (err) {
3754
console.log(err.message) // #sadpanda
38-
})
55+
});
56+
57+
:markdown
58+
Subdocuments' `pre('save')` and `pre('validate')` middleware execute
59+
**before** the top-level document's `pre('save')` but **after** the
60+
top-level document's `pre('validate')` middleware. This is because validating
61+
before `save()` is actually a piece of built-in middleware.
62+
63+
:js
64+
// Below code will print out 1-4 in order
65+
var childSchema = new mongoose.Schema({ name: 'string' });
66+
67+
childSchema.pre('validate', function(next) {
68+
console.log('2');
69+
next();
70+
});
71+
72+
childSchema.pre('save', function(next) {
73+
console.log('3');
74+
next();
75+
});
76+
77+
var parentSchema = new mongoose.Schema({
78+
child: childSchema,
79+
});
80+
81+
parentSchema.pre('validate', function(next) {
82+
console.log('1');
83+
next();
84+
});
85+
86+
parentSchema.pre('save', function(next) {
87+
console.log('4');
88+
next();
89+
});
90+
3991

4092
h3 Finding a sub-document
4193
:markdown
42-
Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`.
94+
Each subdocument has an `_id` by default. Mongoose document arrays have a
95+
special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method
96+
for searching a document array to find a document with a given `_id`.
4397
:js
4498
var doc = parent.children.id(_id);
4599

46-
h3 Adding sub-docs
100+
h3 Adding sub-docs to arrays
47101
:markdown
48102
MongooseArray methods such as
49103
[push](./api.html#types_array_MongooseArray.push),
@@ -71,50 +125,36 @@ block content
71125
:js
72126
var newdoc = parent.children.create({ name: 'Aaron' });
73127

74-
h3 Removing docs
128+
h3 Removing subdocs
75129
:markdown
76-
Each sub-document has it's own
77-
[remove](./api.html#types_embedded_EmbeddedDocument-remove) method.
130+
Each subdocument has it's own
131+
[remove](./api.html#types_embedded_EmbeddedDocument-remove) method. For
132+
an array subdocument, this is equivalent to calling `.pull()` on the
133+
subdocument. For a single nested subdocument, `remove()` is equivalent
134+
to setting the subdocument to `null`.
78135
:js
79-
var doc = parent.children.id(_id).remove();
136+
// Equivalent to `parent.children.pull(_id)`
137+
parent.children.id(_id).remove();
138+
// Equivalent to `parent.child = null`
139+
parent.child.remove();
80140
parent.save(function (err) {
81141
if (err) return handleError(err);
82-
console.log('the sub-doc was removed')
142+
console.log('the subdocs were removed');
83143
});
84144

85-
h4#altsyntax Alternate declaration syntax
145+
h4#altsyntax Alternate declaration syntax for arrays
86146
:markdown
87-
If you don't need access to the sub-document schema instance,
88-
you may also declare sub-docs by simply passing an object literal:
147+
If you create a schema with an array of objects, mongoose will automatically
148+
convert the object to a schema for you:
89149
:js
90150
var parentSchema = new Schema({
91151
children: [{ name: 'string' }]
92-
})
93-
94-
h4#single-embedded Single Embedded Subdocs
95-
:markdown
96-
**New in 4.2.0**
97-
98-
You can also embed schemas without using arrays.
99-
:js
100-
var childSchema = new Schema({ name: 'string' });
101-
102-
var parentSchema = new Schema({
103-
child: childSchema
104152
});
105-
:markdown
106-
A single embedded sub-document behaves similarly to an embedded array.
107-
It only gets saved when the parent document gets saved and its pre/post
108-
document middleware gets executed.
109-
:js
110-
childSchema.pre('save', function(next) {
111-
console.log(this.name); // prints 'Leia'
153+
// Equivalent
154+
var parentSchema = new Schema({
155+
children: [new Schema({ name: 'string' })]
112156
});
113-
var Parent = mongoose.model('Parent', parentSchema);
114-
var parent = new Parent({ child: { name: 'Luke' } })
115-
parent.child.name = 'Leia';
116-
parent.save(callback); // Triggers the pre middleware.
117-
157+
118158
h3#next Next Up
119159
:markdown
120160
Now that we've covered `Sub-documents`, let's take a look at

0 commit comments

Comments
 (0)