Skip to content

Commit

Permalink
Merge branch '5.10' into gh-9188
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Aug 12, 2020
2 parents 065d549 + 7006532 commit 2b075ee
Show file tree
Hide file tree
Showing 66 changed files with 1,772 additions and 888 deletions.
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ examples/
.vscode
.eslintignore
CONTRIBUTING.md
HISTORY.md
format_deps.js
release-items.md
static.js
Expand Down
66 changes: 66 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,69 @@
5.9.28 / 2020-08-07
===================
* fix(connection): consistently stop buffering when "reconnected" is emitted #9295
* fix(error): ensure `name` and `message` show up on individual ValidatorErrors when calling JSON.stringify() on a ValidationError #9296
* fix(document): keeps manually populated paths when setting a nested path to itself #9293
* fix(document): allow saving after setting document array to itself #9266
* fix(schema): handle `match` schema validator with `/g` flag #9287
* docs(guide): refactor transactions examples to async/await #9204

5.9.27 / 2020-07-31
===================
* fix: upgrade mongodb driver -> 3.5.10 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
* docs(transactions): make transactions docs use async/await for readability #9204

5.9.26 / 2020-07-27
===================
* fix(document): allow unsetting boolean field by setting the field to `undefined` #9275
* fix(document): throw error when overwriting a single nested subdoc changes an immutable path within the subdoc #9281
* fix(timestamps): apply timestamps to `bulkWrite()` updates when not using `$set` #9268
* fix(browser): upgrade babel to v7 to work around an issue with `extends Error` #9273
* fix: make subdocument's `invalidate()` methods have the same return value as top-level document #9271
* docs(model): make `create()` docs use async/await, and add another warning about how `create()` with options requires array syntax #9280
* docs(connections): clarify that Mongoose can emit 'connected' when reconnecting after losing connectivity #9240
* docs(populate): clarify that you can't filter based on foreign document properties when populating #9279
* docs(document+model): clarify how `validateModifiedOnly` option works #9263
* docs: remove extra poolSize option in comment #9270 [shahvicky](https://github.com/shahvicky)
* docs: point bulkWrite() link to mongoose docs instead of localhost #9284

5.9.25 / 2020-07-17
===================
* fix(discriminator): allow passing a compiled model's schema as a parameter to `discriminator()` #9238
* fix(connection): throw more readable error when querying db before initial connection when `bufferCommands = false` #9239
* fix(indexes): don't unnecessarily drop text indexes when running `syncIndexes()` #9225
* fix: make Boolean _castNullish respect omitUndefined #9242 [ehpc](https://github.com/ehpc)
* fix(populate): populate single nested discriminator underneath doc array when populated docs have different model but same id #9244
* docs(mongoose): correct formatting typo #9247 [JNa0](https://github.com/JNa0)

5.9.24 / 2020-07-13
===================
* fix(connection): respect connection-level `bufferCommands` option if `mongoose.connect()` is called after `mongoose.model()` #9179
* fix(document): clear out `priorDoc` after overwriting single nested subdoc so changes after overwrite get persisted correctly #9208
* fix(connection): dont overwrite user-specified `bufferMaxEntries` when setting `bufferCommands` #9218
* fix(model): allow passing projection to `Model.hydrate()` #9209
* fix(schema+document): support adding `null` to schema boolean's `convertToFalse` set #9223
* docs(model): make `find` and `findOne()` examples use async/await and clarify `find({})` is find all #9210

4.13.21 / 2020-07-12
====================
* fix(query): delete top-level `_bsontype` property in queries to prevent silent empty queries #8222

5.9.23 / 2020-07-10
===================
* fix(model): fix `syncIndexes()` error when db index has a collation but Mongoose index does not #9224 [clhuang](https://github.com/clhuang)
* fix(array): only cast array to proper depth if it contains an non-array value #9217 #9215 [cyrilgandon](https://github.com/cyrilgandon)
* docs(schematype): document the `transform` option #9211
* docs(mongoose): fix typo #9212 [JNa0](https://github.com/JNa0)

5.9.22 / 2020-07-06
===================
* fix(schema): treat `{ type: mongoose.Schema.Types.Array }` as equivalent to `{ type: Array }` #9194
* fix: revert fix for #9107 to avoid issues when calling `connect()` multiple times #9167
* fix(update): respect storeSubdocValidationError option with update validators #9172
* fix: upgrade to safe-buffer 5.2 #9198
* docs: add a note about SSL validation to migration guide #9147
* docs(schemas): fix inconsistent header #9196 [samtsai15](https://github.com/samtsai15)

5.9.21 / 2020-07-01
===================
* fix: propagate `typeKey` option to implicitly created schemas from `typePojoToMixed` #9185 [joaoritter](https://github.com/joaoritter)
Expand Down
33 changes: 10 additions & 23 deletions docs/browser.pug
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ block content
[discriminators](http://mongoosejs.com/docs/discriminators.html),
or any other Mongoose feature other than schemas and validating documents.

Use the below syntax to access the Mongoose browser library.
Mongoose has a pre-built bundle of the browser library. If you're bundling your code with [Webpack](https://webpack.js.org/),
you should be able to import Mongoose's browser library as shown below if your Webpack `target` is `'web'`:

```javascript
import mongoose from 'mongoose';
```

You can use the below syntax to access the Mongoose browser library from Node.js:

```javascript
// Using `require()`
Expand All @@ -40,7 +47,6 @@ block content

<ul class="toc">
<li><a href="#usage">Using the Browser Library</a></li>
<li><a href="#webpack">Building With Webpack</a></li>
</ul>


Expand All @@ -50,7 +56,7 @@ block content
is validating documents as shown below.

```javascript
import mongoose from 'mongoose/browser';
import mongoose from 'mongoose';

// Mongoose's browser library does **not** have models. It only supports
// schemas and documents. The primary use case is validating documents
Expand All @@ -60,23 +66,4 @@ block content
}));
// Prints an error because `name` is required.
console.log(doc.validateSync());
```

<h2 id="webpack">Building With Webpack</h2>

Mongoose uses [ES2015 (also known as ES6)](https://www.ecma-international.org/ecma-262/6.0/)
syntax, so in order to use Mongoose with older browsers you'll need to use
a tool like [Babel](https://www.npmjs.com/package/babel-cli). As of version
5.x, Mongoose no longer has an officially supported pre-built browser bundle,
you need to compile the browser library yourself.

To build Mongoose's browser library using Webpack, you'll need to use
[`babel-loader`](https://www.npmjs.com/package/babel-loader). Because of
how Webpack loads `require()` statements, it pulls in a lot of built-in
Node.js modules. In order to avoid this, you need to use the
[`node` Webpack config option](https://webpack.js.org/configuration/node/)
as shown below.

```javascript
[require:webpack.*browser build$]
```
```
7 changes: 6 additions & 1 deletion docs/connections.pug
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ block content
connection may emit.

* `connecting`: Emitted when Mongoose starts making its initial connection to the MongoDB server
* `connected`: Emitted when Mongoose successfully makes its initial connection to the MongoDB server
* `connected`: Emitted when Mongoose successfully makes its initial connection to the MongoDB server, or when Mongoose reconnects after losing connectivity.
* `open`: Equivalent to `connected`
* `disconnecting`: Your app called [`Connection#close()`](api.html#connection_Connection-close) to disconnect from MongoDB
* `disconnected`: Emitted when Mongoose lost connection to the MongoDB server. This event may be due to your code explicitly closing the connection, the database server crashing, or network connectivity issues.
Expand All @@ -284,6 +284,11 @@ block content
* `all`: Emitted when you're connecting to a replica set and Mongoose has successfully connected to all servers specified in your connection string.
* `reconnectFailed`: Emitted when you're connected to a standalone server and Mongoose has run out of [`reconnectTries`](https://thecodebarbarian.com/managing-connections-with-the-mongodb-node-driver.html#handling-single-server-outages). The [MongoDB driver](http://npmjs.com/package/mongodb) will no longer attempt to reconnect after this event is emitted. This event will never be emitted if you're connected to a replica set.

When you're connecting to a single MongoDB server (a "standalone"), Mongoose will emit 'disconnected' if it gets
disconnected from the standalone server, and 'connected' if it successfully connects to the standalone. In a
replica set with `useUnifiedTopology = true`, Mongoose will emit 'disconnected' if it loses connectivity to
_every_ server in the replica set, and 'connected' if it manages to reconnect to at least one server in the replica set.

<h3 id="keepAlive"><a href="#keepAlive">A note about keepAlive</a></h3>

For long running applications, it is often prudent to enable `keepAlive`
Expand Down
72 changes: 69 additions & 3 deletions docs/guide.pug
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ block content
- [useNestedStrict](#useNestedStrict)
- [validateBeforeSave](#validateBeforeSave)
- [versionKey](#versionKey)
- [optimisticConcurrency](#optimisticConcurrency)
- [collation](#collation)
- [selectPopulatedPaths](#selectPopulatedPaths)
- [skipVersioning](#skipVersioning)
Expand Down Expand Up @@ -891,9 +892,8 @@ block content
thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
```

Note that Mongoose versioning is **not** a full [optimistic concurrency](https://en.wikipedia.org/wiki/Optimistic_concurrency_control)
solution. Use [mongoose-update-if-current](https://github.com/eoin-obrien/mongoose-update-if-current)
for OCC support. Mongoose versioning only operates on arrays:
Note that Mongoose's default versioning is **not** a full [optimistic concurrency](https://en.wikipedia.org/wiki/Optimistic_concurrency_control)
solution. Mongoose's default versioning only operates on arrays as shown below.

```javascript
// 2 copies of the same document
Expand All @@ -911,6 +911,8 @@ block content
await doc2.save();
```

If you need optimistic concurrency support for `save()`, you can set the [`optimisticConcurrency` option](#optimisticConcurrency)

Document versioning can also be disabled by setting the `versionKey` to
`false`.
_DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.blogspot.com/2012/06/mongoose-v3-part-1-versioning.html)._
Expand Down Expand Up @@ -946,6 +948,70 @@ block content
});
```

<h3 id="optimisticConcurrency"><a href="#optimisticConcurrency">option: optimisticConcurrency</a></h3>

[Optimistic concurrency](https://en.wikipedia.org/wiki/Optimistic_concurrency_control) is a strategy to ensure
the document you're updating didn't change between when you loaded it using `find()` or `findOne()`, and when
you update it using `save()`.

For example, suppose you have a `House` model that contains a list of `photos`, and a `status` that represents
whether this house shows up in searches. Suppose that a house that has status `'APPROVED'` must have at least
two `photos`. You might implement the logic of approving a house document as shown below:

```javascript
async function markApproved(id) {
const house = await House.findOne({ _id });
if (house.photos.length < 2) {
throw new Error('House must have at least two photos!');
}

house.status = 'APPROVED';
await house.save();
}
```

The `markApproved()` function looks right in isolation, but there might be a potential issue: what if another
function removes the house's photos between the `findOne()` call and the `save()` call? For example, the below
code will succeed:

```javascript
const house = await House.findOne({ _id });
if (house.photos.length < 2) {
throw new Error('House must have at least two photos!');
}

const house2 = await House.findOne({ _id });
house2.photos = [];
await house2.save();

// Marks the house as 'APPROVED' even though it has 0 photos!
house.status = 'APPROVED';
await house.save();
```

If you set the `optimisticConcurrency` option on the `House` model's schema, the above script will throw an
error.

```javascript
const House = mongoose.model('House', Schema({
status: String,
photos: [String]
}, { optimisticConcurrency: true }));

const house = await House.findOne({ _id });
if (house.photos.length < 2) {
throw new Error('House must have at least two photos!');
}

const house2 = await House.findOne({ _id });
house2.photos = [];
await house2.save();

// Throws 'VersionError: No matching document found for id "..." version 0'
house.status = 'APPROVED';
await house.save();
```

<h3 id="collation"><a href="#collation">option: collation</a></h3>

Sets a default [collation](https://docs.mongodb.com/manual/reference/collation/)
Expand Down
6 changes: 3 additions & 3 deletions docs/migrating_to_5.pug
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ block content
Connection Logic and `useMongoClient`
</a></h3>

The [`useMongoClient` option](http://mongoosejs.com/docs/4.x/docs/connections.html#use-mongo-client) was
The [`useMongoClient` option](/docs/4.x/docs/connections.html#use-mongo-client) was
removed in Mongoose 5, it is now always `true`. As a consequence, Mongoose 5
no longer supports several function signatures for `mongoose.connect()` that
worked in Mongoose 4.x if the `useMongoClient` option was off. Below are some
Expand Down Expand Up @@ -489,7 +489,7 @@ block content
</a></h3>

Mongoose 5.x uses version 3.x of the [MongoDB Node.js driver](http://npmjs.com/package/mongodb). MongoDB driver 3.x changed the format of
the result of [`bulkWrite()` calls](http://localhost:8088/docs/api.html#model_Model.bulkWrite) so there is no longer a top-level `nInserted`, `nModified`, etc. property. The new result object structure is [described here](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~BulkWriteOpResult).
the result of [`bulkWrite()` calls](/docs/api.html#model_Model.bulkWrite) so there is no longer a top-level `nInserted`, `nModified`, etc. property. The new result object structure is [described here](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~BulkWriteOpResult).

```javascript
const Model = mongoose.model('Test', new Schema({ name: String }));
Expand Down Expand Up @@ -569,4 +569,4 @@ block content

```javascript
mongoose.connect(uri, { tlsInsecure: false }); // Opt out of additional SSL validation
```
```
29 changes: 28 additions & 1 deletion docs/populate.pug
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ block content

```javascript
Story.
find(...).
find().
populate({
path: 'fans',
match: { age: { $gte: 21 } },
Expand All @@ -266,6 +266,33 @@ block content
exec();
```

The `match` option doesn't filter out `Story` documents. If there are no documents that satisfy `match`,
you'll get a `Story` document with an empty `fans` array.

For example, suppose you `populate()` a story's `author` and the `author` doesn't satisfy `match`. Then
the story's `author` will be `null`.

```javascript
const story = await Story.
findOne({ title: 'Casino Royale' }).
populate({ path: 'author', name: { $ne: 'Ian Fleming' } }).
exec();
story.author; // `null`
```

In general, there is no way to make `populate()` filter stories based on properties of the story's `author`.
For example, the below query won't return any results, even though `author` is populated.

```javascript
const story = await Story.
findOne({ 'author.name': 'Ian Fleming' }).
populate('author').
exec();
story; // null
```

If you want to filter stories by their author's name, you should use [denormalization](https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-3).

<h3 id="limit-vs-perDocumentLimit"><a href="#limit-vs-perDocumentLimit">limit vs. perDocumentLimit</a></h3>

Populate does support a `limit` option, however, it currently
Expand Down
7 changes: 4 additions & 3 deletions docs/schematypes.pug
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,10 @@ block content
* `set`: function, defines a custom setter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).
* `alias`: string, mongoose >= 4.10.0 only. Defines a [virtual](./guide.html#virtuals) with the given name that gets/sets this path.
* `immutable`: boolean, defines path as immutable. Mongoose prevents you from changing immutable paths unless the parent document has `isNew: true`.
* `transform`: function, Mongoose calls this function when you call [`Document#toJSON()`](/docs/api/document.html#document_Document-toJSON) function, including when you [`JSON.stringify()`](https://thecodebarbarian.com/the-80-20-guide-to-json-stringify-in-javascript) a document.

```javascript
var numberSchema = new Schema({
const numberSchema = new Schema({
integerOnly: {
type: Number,
get: v => Math.round(v),
Expand All @@ -249,9 +250,9 @@ block content
}
});

var Number = mongoose.model('Number', numberSchema);
const Number = mongoose.model('Number', numberSchema);

var doc = new Number();
const doc = new Number();
doc.integerOnly = 2.001;
doc.integerOnly; // 2
doc.i; // 2
Expand Down

0 comments on commit 2b075ee

Please sign in to comment.