mongoose 5.7.8 → 5.7.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/History.md +33 -0
- package/README.md +20 -15
- package/lib/connection.js +14 -5
- package/lib/document.js +16 -11
- package/lib/helpers/cursor/eachAsync.js +6 -8
- package/lib/helpers/discriminator/getConstructor.js +1 -1
- package/lib/helpers/discriminator/getDiscriminatorByValue.js +27 -0
- package/lib/helpers/model/castBulkWrite.js +6 -0
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +5 -1
- package/lib/helpers/populate/getModelsMapForPopulate.js +12 -5
- package/lib/helpers/schema/getIndexes.js +2 -1
- package/lib/index.js +45 -0
- package/lib/model.js +7 -3
- package/lib/options/SchemaArrayOptions.js +1 -6
- package/lib/options/SchemaBufferOptions.js +1 -6
- package/lib/options/SchemaDateOptions.js +1 -6
- package/lib/options/SchemaDocumentArrayOptions.js +48 -0
- package/lib/options/SchemaMapOptions.js +43 -0
- package/lib/options/SchemaNumberOptions.js +1 -6
- package/lib/options/SchemaObjectIdOptions.js +1 -6
- package/lib/options/SchemaStringOptions.js +1 -6
- package/lib/options/SchemaTypeOptions.js +1 -6
- package/lib/options/propertyOptions.js +8 -0
- package/lib/query.js +2 -5
- package/lib/queryhelpers.js +2 -28
- package/lib/schema/array.js +1 -1
- package/lib/schema/documentarray.js +3 -0
- package/lib/schema/map.js +3 -0
- package/lib/schema.js +14 -8
- package/lib/types/documentarray.js +18 -10
- package/lib/utils.js +12 -0
- package/package.json +11 -3
package/History.md
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
5.7.12 / 2019-11-19
|
|
2
|
+
===================
|
|
3
|
+
* fix: avoid throwing error if calling `push()` on a doc array with no parent #8351 #8317 #8312 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
|
|
4
|
+
* fix(connection): only buffer for "open" events when calling connection helper while connecting #8319
|
|
5
|
+
* fix(connection): pull default database from connection string if specified #8355 #8354 [zachazar](https://github.com/zachazar)
|
|
6
|
+
* fix(populate+discriminator): handle populating document whose discriminator value is different from discriminator model name #8324
|
|
7
|
+
* fix: add `mongoose.isValidObjectId()` function to test whether Mongoose can cast a value to an objectid #3823
|
|
8
|
+
* fix(model): support setting `excludeIndexes` as schema option for subdocs #8343
|
|
9
|
+
* fix: add SchemaMapOptions class for options to map schematype #8318
|
|
10
|
+
* docs(query): remove duplicate omitUndefined options #8349 [mdumandag](https://github.com/mdumandag)
|
|
11
|
+
* docs(schema): add Schema#paths docs to public API docs #8340
|
|
12
|
+
|
|
13
|
+
5.7.11 / 2019-11-14
|
|
14
|
+
===================
|
|
15
|
+
* fix: update mongodb driver -> 3.3.4 #8276
|
|
16
|
+
* fix(model): throw readable error when casting bulkWrite update without a 'filter' or 'update' #8332 #8331 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
|
|
17
|
+
* fix(connection): bubble up connected/disconnected events with unified topology #8338 #8337
|
|
18
|
+
* fix(model): delete $versionError after saving #8326 #8048 [Fonger](https://github.com/Fonger)
|
|
19
|
+
* test(model): add test for issue #8040 #8341 [Fonger](https://github.com/Fonger)
|
|
20
|
+
|
|
21
|
+
5.7.10 / 2019-11-11
|
|
22
|
+
===================
|
|
23
|
+
* perf(cursor): remove unnecessary `setTimeout()` in `eachAsync()`, 4x speedup in basic benchmarks #8310
|
|
24
|
+
* docs(README): re-order sections for better readability #8321 [dandv](https://github.com/dandv)
|
|
25
|
+
* chore: make npm test not hard-code file paths #8322 [stieg](https://github.com/stieg)
|
|
26
|
+
|
|
27
|
+
5.7.9 / 2019-11-08
|
|
28
|
+
==================
|
|
29
|
+
* fix(schema): support setting schema path to an instance of SchemaTypeOptions to fix integration with mongoose-i18n-localize #8297 #8292
|
|
30
|
+
* fix(populate): make `retainNullValues` set array element to `null` if foreign doc with that id was not found #8293
|
|
31
|
+
* fix(document): support getter setting virtual on manually populated doc when calling toJSON() #8295
|
|
32
|
+
* fix(model): allow objects with `toBSON()` to make it to `save()` #8299
|
|
33
|
+
|
|
1
34
|
5.7.8 / 2019-11-04
|
|
2
35
|
==================
|
|
3
36
|
* fix(document): allow manually populating path within document array #8273
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Mongoose
|
|
2
2
|
|
|
3
|
-
Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment.
|
|
3
|
+
Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.
|
|
4
4
|
|
|
5
5
|
[](http://slack.mongoosejs.io)
|
|
6
6
|
[](https://travis-ci.org/Automattic/mongoose)
|
|
@@ -22,16 +22,6 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed
|
|
|
22
22
|
- [Help Forum](http://groups.google.com/group/mongoose-orm)
|
|
23
23
|
- [MongoDB Support](https://docs.mongodb.org/manual/support/)
|
|
24
24
|
|
|
25
|
-
## Importing
|
|
26
|
-
|
|
27
|
-
```javascript
|
|
28
|
-
// Using Node.js `require()`
|
|
29
|
-
const mongoose = require('mongoose');
|
|
30
|
-
|
|
31
|
-
// Using ES6 imports
|
|
32
|
-
import mongoose from 'mongoose';
|
|
33
|
-
```
|
|
34
|
-
|
|
35
25
|
## Plugins
|
|
36
26
|
|
|
37
27
|
Check out the [plugins search site](http://plugins.mongoosejs.io/) to see hundreds of related modules from the community. Next, learn how to write your own plugin from the [docs](http://mongoosejs.com/docs/plugins.html) or [this blog post](http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins).
|
|
@@ -55,6 +45,16 @@ First install [node.js](http://nodejs.org/) and [mongodb](https://www.mongodb.or
|
|
|
55
45
|
$ npm install mongoose
|
|
56
46
|
```
|
|
57
47
|
|
|
48
|
+
## Importing
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
// Using Node.js `require()`
|
|
52
|
+
const mongoose = require('mongoose');
|
|
53
|
+
|
|
54
|
+
// Using ES6 imports
|
|
55
|
+
import mongoose from 'mongoose';
|
|
56
|
+
```
|
|
57
|
+
|
|
58
58
|
## Overview
|
|
59
59
|
|
|
60
60
|
### Connecting to MongoDB
|
|
@@ -64,9 +64,7 @@ First, we need to define a connection. If your app uses only one database, you s
|
|
|
64
64
|
Both `connect` and `createConnection` take a `mongodb://` URI, or the parameters `host, database, port, options`.
|
|
65
65
|
|
|
66
66
|
```js
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
mongoose.connect('mongodb://localhost/my_database', {
|
|
67
|
+
await mongoose.connect('mongodb://localhost/my_database', {
|
|
70
68
|
useNewUrlParser: true,
|
|
71
69
|
useUnifiedTopology: true
|
|
72
70
|
});
|
|
@@ -172,7 +170,14 @@ MyModel.find({}, function (err, docs) {
|
|
|
172
170
|
});
|
|
173
171
|
```
|
|
174
172
|
|
|
175
|
-
You can also `findOne`, `findById`, `update`, etc.
|
|
173
|
+
You can also `findOne`, `findById`, `update`, etc.
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
const instance = await MyModel.findOne({ ... });
|
|
177
|
+
console.log(instance.my.key); // 'hello'
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
For more details check out [the docs](http://mongoosejs.com/docs/queries.html).
|
|
176
181
|
|
|
177
182
|
**Important!** If you opened a separate connection using `mongoose.createConnection()` but attempt to access the model through `mongoose.model('ModelName')` it will not work as expected since it is not hooked up to an active db connection. In this case access your model through the connection you created:
|
|
178
183
|
|
package/lib/connection.js
CHANGED
|
@@ -420,7 +420,7 @@ function _wrapConnHelper(fn) {
|
|
|
420
420
|
Array.prototype.slice.call(arguments, 0, arguments.length - 1) :
|
|
421
421
|
Array.prototype.slice.call(arguments);
|
|
422
422
|
return utils.promiseOrCallback(cb, cb => {
|
|
423
|
-
if (this.readyState
|
|
423
|
+
if (this.readyState === STATES.connecting) {
|
|
424
424
|
this.once('open', function() {
|
|
425
425
|
fn.apply(this, argsWithoutCb.concat([cb]));
|
|
426
426
|
});
|
|
@@ -605,7 +605,13 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
605
605
|
if (err) {
|
|
606
606
|
return reject(err);
|
|
607
607
|
}
|
|
608
|
-
|
|
608
|
+
if (dbName) {
|
|
609
|
+
this.name = dbName;
|
|
610
|
+
} else if (parsed.defaultDatabase) {
|
|
611
|
+
this.name = parsed.defaultDatabase;
|
|
612
|
+
} else {
|
|
613
|
+
this.name = get(parsed, 'auth.db', null);
|
|
614
|
+
}
|
|
609
615
|
this.host = get(parsed, 'hosts.0.host', 'localhost');
|
|
610
616
|
this.port = get(parsed, 'hosts.0.port', 27017);
|
|
611
617
|
this.user = this.user || get(parsed, 'auth.username');
|
|
@@ -643,11 +649,14 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
643
649
|
if (options.useUnifiedTopology) {
|
|
644
650
|
if (type === 'Single') {
|
|
645
651
|
const server = Array.from(db.s.topology.s.servers.values())[0];
|
|
646
|
-
server.s.pool.on('
|
|
652
|
+
server.s.pool.on('close', () => {
|
|
653
|
+
_this.readyState = STATES.disconnected;
|
|
654
|
+
});
|
|
655
|
+
server.s.topology.on('serverHeartbeatSucceeded', () => {
|
|
647
656
|
_handleReconnect();
|
|
648
657
|
});
|
|
649
|
-
server.s.pool.on('
|
|
650
|
-
|
|
658
|
+
server.s.pool.on('reconnect', () => {
|
|
659
|
+
_handleReconnect();
|
|
651
660
|
});
|
|
652
661
|
server.s.pool.on('timeout', () => {
|
|
653
662
|
_this.emit('timeout');
|
package/lib/document.js
CHANGED
|
@@ -2836,6 +2836,13 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
2836
2836
|
minimize: _minimize
|
|
2837
2837
|
});
|
|
2838
2838
|
|
|
2839
|
+
if (utils.hasUserDefinedProperty(options, 'getters')) {
|
|
2840
|
+
cloneOptions.getters = options.getters;
|
|
2841
|
+
}
|
|
2842
|
+
if (utils.hasUserDefinedProperty(options, 'virtuals')) {
|
|
2843
|
+
cloneOptions.virtuals = options.virtuals;
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2839
2846
|
const depopulate = options.depopulate ||
|
|
2840
2847
|
get(options, '_parentOptions.depopulate', false);
|
|
2841
2848
|
// _isNested will only be true if this is not the top level document, we
|
|
@@ -2852,6 +2859,10 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
2852
2859
|
options.minimize = _minimize;
|
|
2853
2860
|
|
|
2854
2861
|
cloneOptions._parentOptions = options;
|
|
2862
|
+
cloneOptions._skipSingleNestedGetters = true;
|
|
2863
|
+
|
|
2864
|
+
const gettersOptions = Object.assign({}, cloneOptions);
|
|
2865
|
+
gettersOptions._skipSingleNestedGetters = false;
|
|
2855
2866
|
|
|
2856
2867
|
// remember the root transform function
|
|
2857
2868
|
// to save it from being overwritten by sub-transform functions
|
|
@@ -2860,16 +2871,15 @@ Document.prototype.$toObject = function(options, json) {
|
|
|
2860
2871
|
let ret = clone(this._doc, cloneOptions) || {};
|
|
2861
2872
|
|
|
2862
2873
|
if (options.getters) {
|
|
2863
|
-
applyGetters(this, ret,
|
|
2864
|
-
|
|
2865
|
-
// if minimize is set, we need to remove them.
|
|
2874
|
+
applyGetters(this, ret, gettersOptions);
|
|
2875
|
+
|
|
2866
2876
|
if (options.minimize) {
|
|
2867
2877
|
ret = minimize(ret) || {};
|
|
2868
2878
|
}
|
|
2869
2879
|
}
|
|
2870
2880
|
|
|
2871
|
-
if (options.virtuals || options.getters && options.virtuals !== false) {
|
|
2872
|
-
applyVirtuals(this, ret,
|
|
2881
|
+
if (options.virtuals || (options.getters && options.virtuals !== false)) {
|
|
2882
|
+
applyVirtuals(this, ret, gettersOptions, options);
|
|
2873
2883
|
}
|
|
2874
2884
|
|
|
2875
2885
|
if (options.versionKey === false && this.schema.options.versionKey) {
|
|
@@ -3180,12 +3190,7 @@ function applyGetters(self, json, options) {
|
|
|
3180
3190
|
v = cur[part];
|
|
3181
3191
|
if (ii === last) {
|
|
3182
3192
|
const val = self.get(path);
|
|
3183
|
-
|
|
3184
|
-
// before `applyGetters()` in `$toObject()`. Quirk because single
|
|
3185
|
-
// nested subdocs are hydrated docs in `_doc` as opposed to POJOs.
|
|
3186
|
-
if (val != null && val.$__ == null) {
|
|
3187
|
-
branch[part] = clone(val, options);
|
|
3188
|
-
}
|
|
3193
|
+
branch[part] = clone(val, options);
|
|
3189
3194
|
} else if (v == null) {
|
|
3190
3195
|
if (part in cur) {
|
|
3191
3196
|
branch[part] = v;
|
|
@@ -99,13 +99,11 @@ function asyncQueue() {
|
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
function _step() {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
}, 0);
|
|
102
|
+
inProgress = null;
|
|
103
|
+
if (_queue.length > 0) {
|
|
104
|
+
inProgress = id++;
|
|
105
|
+
const fn = _queue.shift();
|
|
106
|
+
fn(_step);
|
|
107
|
+
}
|
|
110
108
|
}
|
|
111
109
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*!
|
|
4
|
+
* returns discriminator by discriminatorMapping.value
|
|
5
|
+
*
|
|
6
|
+
* @param {Model} model
|
|
7
|
+
* @param {string} value
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
module.exports = function getDiscriminatorByValue(model, value) {
|
|
11
|
+
let discriminator = null;
|
|
12
|
+
if (!model.discriminators) {
|
|
13
|
+
return discriminator;
|
|
14
|
+
}
|
|
15
|
+
for (const name in model.discriminators) {
|
|
16
|
+
const it = model.discriminators[name];
|
|
17
|
+
if (
|
|
18
|
+
it.schema &&
|
|
19
|
+
it.schema.discriminatorMapping &&
|
|
20
|
+
it.schema.discriminatorMapping.value == value
|
|
21
|
+
) {
|
|
22
|
+
discriminator = it;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return discriminator;
|
|
27
|
+
};
|
|
@@ -34,6 +34,9 @@ module.exports = function castBulkWrite(model, op, options) {
|
|
|
34
34
|
op = op['updateOne'];
|
|
35
35
|
return (callback) => {
|
|
36
36
|
try {
|
|
37
|
+
if (!op['filter']) throw new Error('Must provide a filter object.');
|
|
38
|
+
if (!op['update']) throw new Error('Must provide an update object.');
|
|
39
|
+
|
|
37
40
|
op['filter'] = cast(model.schema, op['filter']);
|
|
38
41
|
op['update'] = castUpdate(model.schema, op['update'], {
|
|
39
42
|
strict: model.schema.options.strict,
|
|
@@ -61,6 +64,9 @@ module.exports = function castBulkWrite(model, op, options) {
|
|
|
61
64
|
op = op['updateMany'];
|
|
62
65
|
return (callback) => {
|
|
63
66
|
try {
|
|
67
|
+
if (!op['filter']) throw new Error('Must provide a filter object.');
|
|
68
|
+
if (!op['update']) throw new Error('Must provide an update object.');
|
|
69
|
+
|
|
64
70
|
op['filter'] = cast(model.schema, op['filter']);
|
|
65
71
|
op['update'] = castUpdate(model.schema, op['update'], {
|
|
66
72
|
strict: model.schema.options.strict,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const modelSymbol = require('../symbols').modelSymbol;
|
|
4
|
+
|
|
3
5
|
module.exports = assignRawDocsToIdStructure;
|
|
4
6
|
|
|
5
7
|
/*!
|
|
@@ -63,8 +65,10 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
|
|
|
63
65
|
} else {
|
|
64
66
|
newOrder.push(doc);
|
|
65
67
|
}
|
|
68
|
+
} else if (id != null && id[modelSymbol] != null) {
|
|
69
|
+
newOrder.push(id);
|
|
66
70
|
} else {
|
|
67
|
-
newOrder.push(nullIfNotFound ? null : id);
|
|
71
|
+
newOrder.push(options.retainNullValues || nullIfNotFound ? null : id);
|
|
68
72
|
}
|
|
69
73
|
} else {
|
|
70
74
|
// apply findOne behavior - if document in results, assign, else assign null
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const MongooseError = require('../../error/index');
|
|
4
4
|
const get = require('../get');
|
|
5
|
+
const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
|
|
5
6
|
const isPathExcluded = require('../projection/isPathExcluded');
|
|
6
7
|
const getSchemaTypes = require('./getSchemaTypes');
|
|
7
8
|
const getVirtual = require('./getVirtual');
|
|
@@ -297,12 +298,18 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
297
298
|
|
|
298
299
|
if (!schema && discriminatorKey) {
|
|
299
300
|
modelForFindSchema = utils.getValue(discriminatorKey, doc);
|
|
300
|
-
|
|
301
301
|
if (modelForFindSchema) {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
302
|
+
// `modelForFindSchema` is the discriminator value, so we might need
|
|
303
|
+
// find the discriminated model name
|
|
304
|
+
const discriminatorModel = getDiscriminatorByValue(model, modelForFindSchema);
|
|
305
|
+
if (discriminatorModel != null) {
|
|
306
|
+
modelForCurrentDoc = discriminatorModel;
|
|
307
|
+
} else {
|
|
308
|
+
try {
|
|
309
|
+
modelForCurrentDoc = model.db.model(modelForFindSchema);
|
|
310
|
+
} catch (error) {
|
|
311
|
+
return error;
|
|
312
|
+
}
|
|
306
313
|
}
|
|
307
314
|
|
|
308
315
|
schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
|
|
@@ -36,7 +36,8 @@ module.exports = function getIndexes(schema) {
|
|
|
36
36
|
|
|
37
37
|
if (path.$isMongooseDocumentArray || path.$isSingleNested) {
|
|
38
38
|
if (get(path, 'options.excludeIndexes') !== true &&
|
|
39
|
-
get(path, 'schemaOptions.excludeIndexes') !== true
|
|
39
|
+
get(path, 'schemaOptions.excludeIndexes') !== true &&
|
|
40
|
+
get(path, 'schema.options.excludeIndexes') !== true) {
|
|
40
41
|
collectIndexes(path.schema, prefix + key + '.');
|
|
41
42
|
}
|
|
42
43
|
|
package/lib/index.js
CHANGED
|
@@ -933,6 +933,51 @@ Mongoose.prototype.DocumentProvider = require('./document_provider');
|
|
|
933
933
|
|
|
934
934
|
Mongoose.prototype.ObjectId = SchemaTypes.ObjectId;
|
|
935
935
|
|
|
936
|
+
/**
|
|
937
|
+
* Returns true if Mongoose can cast the given value to an ObjectId, or
|
|
938
|
+
* false otherwise.
|
|
939
|
+
*
|
|
940
|
+
* ####Example:
|
|
941
|
+
*
|
|
942
|
+
* mongoose.isValidObjectId(new mongoose.Types.ObjectId()); // true
|
|
943
|
+
* mongoose.isValidObjectId('0123456789ab'); // true
|
|
944
|
+
* mongoose.isValidObjectId(6); // false
|
|
945
|
+
*
|
|
946
|
+
* @method isValidObjectId
|
|
947
|
+
* @api public
|
|
948
|
+
*/
|
|
949
|
+
|
|
950
|
+
Mongoose.prototype.isValidObjectId = function(v) {
|
|
951
|
+
if (v == null) {
|
|
952
|
+
return true;
|
|
953
|
+
}
|
|
954
|
+
const base = this || mongoose;
|
|
955
|
+
const ObjectId = base.driver.get().ObjectId;
|
|
956
|
+
if (v instanceof ObjectId) {
|
|
957
|
+
return true;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
if (v._id != null) {
|
|
961
|
+
if (v._id instanceof ObjectId) {
|
|
962
|
+
return true;
|
|
963
|
+
}
|
|
964
|
+
if (v._id.toString instanceof Function) {
|
|
965
|
+
v = v._id.toString();
|
|
966
|
+
return typeof v === 'string' && (v.length === 12 || v.length === 24);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
if (v.toString instanceof Function) {
|
|
971
|
+
v = v.toString();
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
if (typeof v === 'string' && (v.length === 12 || v.length === 24)) {
|
|
975
|
+
return true;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
return false;
|
|
979
|
+
};
|
|
980
|
+
|
|
936
981
|
/**
|
|
937
982
|
* The Mongoose Decimal128 [SchemaType](/docs/schematypes.html). Used for
|
|
938
983
|
* declaring paths in your schema that should be
|
package/lib/model.js
CHANGED
|
@@ -30,7 +30,7 @@ const assignVals = require('./helpers/populate/assignVals');
|
|
|
30
30
|
const castBulkWrite = require('./helpers/model/castBulkWrite');
|
|
31
31
|
const discriminator = require('./helpers/model/discriminator');
|
|
32
32
|
const each = require('./helpers/each');
|
|
33
|
-
const getDiscriminatorByValue = require('./
|
|
33
|
+
const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue');
|
|
34
34
|
const getModelsMapForPopulate = require('./helpers/populate/getModelsMapForPopulate');
|
|
35
35
|
const immediate = require('./helpers/immediate');
|
|
36
36
|
const internalToObjectOptions = require('./options').internalToObjectOptions;
|
|
@@ -52,6 +52,10 @@ const modelDbSymbol = Symbol('mongoose#Model#db');
|
|
|
52
52
|
const modelSymbol = require('./helpers/symbols').modelSymbol;
|
|
53
53
|
const subclassedSymbol = Symbol('mongoose#Model#subclassed');
|
|
54
54
|
|
|
55
|
+
const saveToObjectOptions = Object.assign({}, internalToObjectOptions, {
|
|
56
|
+
bson: true
|
|
57
|
+
});
|
|
58
|
+
|
|
55
59
|
/**
|
|
56
60
|
* A Model is a class that's your primary tool for interacting with MongoDB.
|
|
57
61
|
* An instance of a Model is called a [Document](./api.html#Document).
|
|
@@ -244,7 +248,7 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
244
248
|
|
|
245
249
|
if (this.isNew) {
|
|
246
250
|
// send entire doc
|
|
247
|
-
const obj = this.toObject(
|
|
251
|
+
const obj = this.toObject(saveToObjectOptions);
|
|
248
252
|
|
|
249
253
|
if ((obj || {})._id === void 0) {
|
|
250
254
|
// documents must have an _id else mongoose won't know
|
|
@@ -461,7 +465,7 @@ Model.prototype.save = function(options, fn) {
|
|
|
461
465
|
this.$__save(options, error => {
|
|
462
466
|
this.$__.saving = undefined;
|
|
463
467
|
delete this.$__.saveOptions;
|
|
464
|
-
delete this.$__
|
|
468
|
+
delete this.$__.$versionError;
|
|
465
469
|
|
|
466
470
|
if (error) {
|
|
467
471
|
this.$__handleReject(error);
|
|
@@ -17,12 +17,7 @@ const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
|
17
17
|
|
|
18
18
|
class SchemaArrayOptions extends SchemaTypeOptions {}
|
|
19
19
|
|
|
20
|
-
const opts =
|
|
21
|
-
enumerable: true,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
value: null
|
|
25
|
-
};
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
26
21
|
|
|
27
22
|
/**
|
|
28
23
|
* If this is an array of strings, an array of allowed values for this path.
|
|
@@ -17,12 +17,7 @@ const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
|
17
17
|
|
|
18
18
|
class SchemaBufferOptions extends SchemaTypeOptions {}
|
|
19
19
|
|
|
20
|
-
const opts =
|
|
21
|
-
enumerable: true,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
value: null
|
|
25
|
-
};
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
26
21
|
|
|
27
22
|
/**
|
|
28
23
|
* Set the default subtype for this buffer.
|
|
@@ -17,12 +17,7 @@ const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
|
17
17
|
|
|
18
18
|
class SchemaDateOptions extends SchemaTypeOptions {}
|
|
19
19
|
|
|
20
|
-
const opts =
|
|
21
|
-
enumerable: true,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
value: null
|
|
25
|
-
};
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
26
21
|
|
|
27
22
|
/**
|
|
28
23
|
* If set, Mongoose adds a validator that checks that this path is after the
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The options defined on an Document Array schematype.
|
|
7
|
+
*
|
|
8
|
+
* ####Example:
|
|
9
|
+
*
|
|
10
|
+
* const schema = new Schema({ users: [{ name: string }] });
|
|
11
|
+
* schema.path('users').options; // SchemaDocumentArrayOptions instance
|
|
12
|
+
*
|
|
13
|
+
* @api public
|
|
14
|
+
* @inherits SchemaTypeOptions
|
|
15
|
+
* @constructor SchemaDocumentOptions
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
class SchemaDocumentArrayOptions extends SchemaTypeOptions {}
|
|
19
|
+
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* If `true`, Mongoose will skip building any indexes defined in this array's schema.
|
|
24
|
+
* If not set, Mongoose will build all indexes defined in this array's schema.
|
|
25
|
+
*
|
|
26
|
+
* ####Example:
|
|
27
|
+
*
|
|
28
|
+
* const childSchema = Schema({ name: { type: String, index: true } });
|
|
29
|
+
* // If `excludeIndexes` is `true`, Mongoose will skip building an index
|
|
30
|
+
* // on `arr.name`. Otherwise, Mongoose will build an index on `arr.name`.
|
|
31
|
+
* const parentSchema = Schema({
|
|
32
|
+
* arr: { type: [childSchema], excludeIndexes: true }
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* @api public
|
|
36
|
+
* @property excludeIndexes
|
|
37
|
+
* @memberOf SchemaDocumentArrayOptions
|
|
38
|
+
* @type Array
|
|
39
|
+
* @instance
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
Object.defineProperty(SchemaDocumentArrayOptions.prototype, 'excludeIndexes', opts);
|
|
43
|
+
|
|
44
|
+
/*!
|
|
45
|
+
* ignore
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
module.exports = SchemaDocumentArrayOptions;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The options defined on a Map schematype.
|
|
7
|
+
*
|
|
8
|
+
* ####Example:
|
|
9
|
+
*
|
|
10
|
+
* const schema = new Schema({ socialMediaHandles: { type: Map, of: String } });
|
|
11
|
+
* schema.path('socialMediaHandles').options; // SchemaMapOptions instance
|
|
12
|
+
*
|
|
13
|
+
* @api public
|
|
14
|
+
* @inherits SchemaTypeOptions
|
|
15
|
+
* @constructor SchemaMapOptions
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
class SchemaMapOptions extends SchemaTypeOptions {}
|
|
19
|
+
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* If set, specifies the type of this map's values. Mongoose will cast
|
|
24
|
+
* this map's values to the given type.
|
|
25
|
+
*
|
|
26
|
+
* If not set, Mongoose will not cast the map's values.
|
|
27
|
+
*
|
|
28
|
+
* ####Example:
|
|
29
|
+
*
|
|
30
|
+
* // Mongoose will cast `socialMediaHandles` values to strings
|
|
31
|
+
* const schema = new Schema({ socialMediaHandles: { type: Map, of: String } });
|
|
32
|
+
* schema.path('socialMediaHandles').options.of; // String
|
|
33
|
+
*
|
|
34
|
+
* @api public
|
|
35
|
+
* @property of
|
|
36
|
+
* @memberOf SchemaMapOptions
|
|
37
|
+
* @type Function|string
|
|
38
|
+
* @instance
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
Object.defineProperty(SchemaMapOptions.prototype, 'of', opts);
|
|
42
|
+
|
|
43
|
+
module.exports = SchemaMapOptions;
|
|
@@ -17,12 +17,7 @@ const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
|
17
17
|
|
|
18
18
|
class SchemaNumberOptions extends SchemaTypeOptions {}
|
|
19
19
|
|
|
20
|
-
const opts =
|
|
21
|
-
enumerable: true,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
value: null
|
|
25
|
-
};
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
26
21
|
|
|
27
22
|
/**
|
|
28
23
|
* If set, Mongoose adds a validator that checks that this path is at least the
|
|
@@ -17,12 +17,7 @@ const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
|
17
17
|
|
|
18
18
|
class SchemaObjectIdOptions extends SchemaTypeOptions {}
|
|
19
19
|
|
|
20
|
-
const opts =
|
|
21
|
-
enumerable: true,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
value: null
|
|
25
|
-
};
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
26
21
|
|
|
27
22
|
/**
|
|
28
23
|
* If truthy, uses Mongoose's default built-in ObjectId path.
|
|
@@ -17,12 +17,7 @@ const SchemaTypeOptions = require('./SchemaTypeOptions');
|
|
|
17
17
|
|
|
18
18
|
class SchemaStringOptions extends SchemaTypeOptions {}
|
|
19
19
|
|
|
20
|
-
const opts =
|
|
21
|
-
enumerable: true,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
value: null
|
|
25
|
-
};
|
|
20
|
+
const opts = require('./propertyOptions');
|
|
26
21
|
|
|
27
22
|
/**
|
|
28
23
|
* Array of allowed values for this path
|
package/lib/query.js
CHANGED
|
@@ -18,6 +18,7 @@ const castArrayFilters = require('./helpers/update/castArrayFilters');
|
|
|
18
18
|
const castUpdate = require('./helpers/query/castUpdate');
|
|
19
19
|
const completeMany = require('./helpers/query/completeMany');
|
|
20
20
|
const get = require('./helpers/get');
|
|
21
|
+
const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue');
|
|
21
22
|
const hasDollarKeys = require('./helpers/query/hasDollarKeys');
|
|
22
23
|
const helpers = require('./queryhelpers');
|
|
23
24
|
const isInclusive = require('./helpers/projection/isInclusive');
|
|
@@ -3862,7 +3863,6 @@ Query.prototype._replaceOne = wrapThunk(function(callback) {
|
|
|
3862
3863
|
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
|
|
3863
3864
|
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
3864
3865
|
* @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
|
|
3865
|
-
* @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
|
|
3866
3866
|
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
|
|
3867
3867
|
* @param {Function} [callback] params are (error, writeOpResult)
|
|
3868
3868
|
* @return {Query} this
|
|
@@ -3928,7 +3928,6 @@ Query.prototype.update = function(conditions, doc, options, callback) {
|
|
|
3928
3928
|
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
|
|
3929
3929
|
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
3930
3930
|
* @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
|
|
3931
|
-
* @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
|
|
3932
3931
|
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
|
|
3933
3932
|
* @param {Function} [callback] params are (error, writeOpResult)
|
|
3934
3933
|
* @return {Query} this
|
|
@@ -3995,7 +3994,6 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) {
|
|
|
3995
3994
|
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
|
|
3996
3995
|
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
3997
3996
|
* @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
|
|
3998
|
-
* @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
|
|
3999
3997
|
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
|
|
4000
3998
|
* @param {Function} [callback] params are (error, writeOpResult)
|
|
4001
3999
|
* @return {Query} this
|
|
@@ -4060,7 +4058,6 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) {
|
|
|
4060
4058
|
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
|
|
4061
4059
|
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
4062
4060
|
* @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
|
|
4063
|
-
* @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
|
|
4064
4061
|
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
|
|
4065
4062
|
* @param {Function} [callback] params are (error, writeOpResult)
|
|
4066
4063
|
* @return {Query} this
|
|
@@ -4433,7 +4430,7 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) {
|
|
|
4433
4430
|
typeof filter[schema.options.discriminatorKey] !== 'object' &&
|
|
4434
4431
|
schema.discriminators != null) {
|
|
4435
4432
|
const discriminatorValue = filter[schema.options.discriminatorKey];
|
|
4436
|
-
const byValue =
|
|
4433
|
+
const byValue = getDiscriminatorByValue(this.model, discriminatorValue);
|
|
4437
4434
|
schema = schema.discriminators[discriminatorValue] ||
|
|
4438
4435
|
(byValue && byValue.schema) ||
|
|
4439
4436
|
schema;
|
package/lib/queryhelpers.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
const checkEmbeddedDiscriminatorKeyProjection =
|
|
8
8
|
require('./helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection');
|
|
9
9
|
const get = require('./helpers/get');
|
|
10
|
+
const getDiscriminatorByValue =
|
|
11
|
+
require('./helpers/discriminator/getDiscriminatorByValue');
|
|
10
12
|
const isDefiningProjection = require('./helpers/projection/isDefiningProjection');
|
|
11
13
|
const utils = require('./utils');
|
|
12
14
|
|
|
@@ -71,34 +73,6 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query,
|
|
|
71
73
|
return pop;
|
|
72
74
|
};
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
/*!
|
|
76
|
-
* returns discriminator by discriminatorMapping.value
|
|
77
|
-
*
|
|
78
|
-
* @param {Model} model
|
|
79
|
-
* @param {string} value
|
|
80
|
-
*/
|
|
81
|
-
function getDiscriminatorByValue(model, value) {
|
|
82
|
-
let discriminator = null;
|
|
83
|
-
if (!model.discriminators) {
|
|
84
|
-
return discriminator;
|
|
85
|
-
}
|
|
86
|
-
for (const name in model.discriminators) {
|
|
87
|
-
const it = model.discriminators[name];
|
|
88
|
-
if (
|
|
89
|
-
it.schema &&
|
|
90
|
-
it.schema.discriminatorMapping &&
|
|
91
|
-
it.schema.discriminatorMapping.value == value
|
|
92
|
-
) {
|
|
93
|
-
discriminator = it;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return discriminator;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
exports.getDiscriminatorByValue = getDiscriminatorByValue;
|
|
101
|
-
|
|
102
76
|
/*!
|
|
103
77
|
* If the document is a mapped discriminator type, it returns a model instance for that type, otherwise,
|
|
104
78
|
* it returns an instance of the given model.
|
package/lib/schema/array.js
CHANGED
|
@@ -17,7 +17,7 @@ const util = require('util');
|
|
|
17
17
|
const utils = require('../utils');
|
|
18
18
|
const castToNumber = require('./operators/helpers').castToNumber;
|
|
19
19
|
const geospatial = require('./operators/geospatial');
|
|
20
|
-
const getDiscriminatorByValue = require('../
|
|
20
|
+
const getDiscriminatorByValue = require('../helpers/discriminator/getDiscriminatorByValue');
|
|
21
21
|
|
|
22
22
|
let MongooseArray;
|
|
23
23
|
let EmbeddedDoc;
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
const ArrayType = require('./array');
|
|
8
8
|
const CastError = require('../error/cast');
|
|
9
9
|
const EventEmitter = require('events').EventEmitter;
|
|
10
|
+
const SchemaDocumentArrayOptions =
|
|
11
|
+
require('../options/SchemaDocumentArrayOptions');
|
|
10
12
|
const SchemaType = require('../schematype');
|
|
11
13
|
const discriminator = require('../helpers/model/discriminator');
|
|
12
14
|
const get = require('../helpers/get');
|
|
@@ -91,6 +93,7 @@ DocumentArrayPath.options = { castNonArrays: true };
|
|
|
91
93
|
*/
|
|
92
94
|
DocumentArrayPath.prototype = Object.create(ArrayType.prototype);
|
|
93
95
|
DocumentArrayPath.prototype.constructor = DocumentArrayPath;
|
|
96
|
+
DocumentArrayPath.prototype.OptionsConstructor = SchemaDocumentArrayOptions;
|
|
94
97
|
|
|
95
98
|
/*!
|
|
96
99
|
* Ignore
|
package/lib/schema/map.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const MongooseMap = require('../types/map');
|
|
8
|
+
const SchemaMapOptions = require('../options/SchemaMapOptions');
|
|
8
9
|
const SchemaType = require('../schematype');
|
|
9
10
|
|
|
10
11
|
/*!
|
|
@@ -42,4 +43,6 @@ class Map extends SchemaType {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
Map.prototype.OptionsConstructor = SchemaMapOptions;
|
|
47
|
+
|
|
45
48
|
module.exports = Map;
|
package/lib/schema.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
const EventEmitter = require('events').EventEmitter;
|
|
8
8
|
const Kareem = require('kareem');
|
|
9
9
|
const SchemaType = require('./schematype');
|
|
10
|
+
const SchemaTypeOptions = require('./options/SchemaTypeOptions');
|
|
10
11
|
const VirtualType = require('./virtualtype');
|
|
11
12
|
const applyTimestampsToChildren = require('./helpers/update/applyTimestampsToChildren');
|
|
12
13
|
const applyTimestampsToUpdate = require('./helpers/update/applyTimestampsToUpdate');
|
|
@@ -71,6 +72,9 @@ let id = 0;
|
|
|
71
72
|
* - [timestamps](/docs/guide.html#timestamps): object or boolean - defaults to `false`. If true, Mongoose adds `createdAt` and `updatedAt` properties to your schema and manages those properties for you.
|
|
72
73
|
* - [storeSubdocValidationError](/docs/guide.html#storeSubdocValidationError): boolean - Defaults to true. If false, Mongoose will wrap validation errors in single nested document subpaths into a single validation error on the single nested subdoc's path.
|
|
73
74
|
*
|
|
75
|
+
* ####Options for Nested Schemas:
|
|
76
|
+
* - `excludeIndexes`: bool - defaults to `false`. If `true`, skip building indexes on this schema's paths.
|
|
77
|
+
*
|
|
74
78
|
* ####Note:
|
|
75
79
|
*
|
|
76
80
|
* _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into its parent._
|
|
@@ -234,15 +238,17 @@ Object.defineProperty(Schema.prototype, 'childSchemas', {
|
|
|
234
238
|
Schema.prototype.obj;
|
|
235
239
|
|
|
236
240
|
/**
|
|
237
|
-
*
|
|
241
|
+
* The paths defined on this schema. The keys are the top-level paths
|
|
242
|
+
* in this schema, and the values are instances of the SchemaType class.
|
|
238
243
|
*
|
|
239
244
|
* ####Example:
|
|
240
|
-
* {
|
|
241
|
-
*
|
|
242
|
-
* , 'nested.key' : SchemaType,
|
|
243
|
-
* }
|
|
245
|
+
* const schema = new Schema({ name: String }, { _id: false });
|
|
246
|
+
* schema.paths; // { name: SchemaString { ... } }
|
|
244
247
|
*
|
|
245
|
-
*
|
|
248
|
+
* schema.add({ age: Number });
|
|
249
|
+
* schema.paths; // { name: SchemaString { ... }, age: SchemaNumber { ... } }
|
|
250
|
+
*
|
|
251
|
+
* @api public
|
|
246
252
|
* @property paths
|
|
247
253
|
* @memberOf Schema
|
|
248
254
|
* @instance
|
|
@@ -426,7 +432,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
426
432
|
'`, got value "' + obj[key][0] + '"');
|
|
427
433
|
}
|
|
428
434
|
|
|
429
|
-
if (utils.isPOJO(obj[key]) &&
|
|
435
|
+
if ((utils.isPOJO(obj[key]) || obj[key] instanceof SchemaTypeOptions) &&
|
|
430
436
|
(!obj[key][this.options.typeKey] || (this.options.typeKey === 'type' && obj[key].type.type))) {
|
|
431
437
|
if (Object.keys(obj[key]).length) {
|
|
432
438
|
// nested object { last: { name: String }}
|
|
@@ -795,7 +801,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
|
|
795
801
|
// copy of SchemaTypes re: gh-7158 gh-6933
|
|
796
802
|
const MongooseTypes = this.base != null ? this.base.Schema.Types : Schema.Types;
|
|
797
803
|
|
|
798
|
-
if (obj
|
|
804
|
+
if (!utils.isPOJO(obj) && !(obj instanceof SchemaTypeOptions)) {
|
|
799
805
|
const constructorName = utils.getFunctionName(obj.constructor);
|
|
800
806
|
if (constructorName !== 'Object') {
|
|
801
807
|
const oldObj = obj;
|
|
@@ -8,7 +8,7 @@ const CoreMongooseArray = require('./core_array');
|
|
|
8
8
|
const Document = require('../document');
|
|
9
9
|
const ObjectId = require('./objectid');
|
|
10
10
|
const castObjectId = require('../cast/objectid');
|
|
11
|
-
const getDiscriminatorByValue = require('../
|
|
11
|
+
const getDiscriminatorByValue = require('../helpers/discriminator/getDiscriminatorByValue');
|
|
12
12
|
const internalToObjectOptions = require('../options').internalToObjectOptions;
|
|
13
13
|
const util = require('util');
|
|
14
14
|
const utils = require('../utils');
|
|
@@ -172,6 +172,14 @@ class CoreDocumentArray extends CoreMongooseArray {
|
|
|
172
172
|
}));
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
slice() {
|
|
176
|
+
const arr = super.slice.apply(this, arguments);
|
|
177
|
+
arr[arrayParentSymbol] = this[arrayParentSymbol];
|
|
178
|
+
arr[arrayPathSymbol] = this[arrayPathSymbol];
|
|
179
|
+
|
|
180
|
+
return arr;
|
|
181
|
+
}
|
|
182
|
+
|
|
175
183
|
/**
|
|
176
184
|
* Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
|
|
177
185
|
*
|
|
@@ -320,18 +328,18 @@ if (util.inspect.custom) {
|
|
|
320
328
|
|
|
321
329
|
function _updateParentPopulated(arr) {
|
|
322
330
|
const parent = arr[arrayParentSymbol];
|
|
323
|
-
if (parent.$__.populated
|
|
324
|
-
const populatedPaths = Object.keys(parent.$__.populated).
|
|
325
|
-
filter(p => p.startsWith(arr[arrayPathSymbol] + '.'));
|
|
331
|
+
if (!parent || parent.$__.populated == null) return;
|
|
326
332
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if (!Array.isArray(parent.$__.populated[path].value)) {
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
333
|
+
const populatedPaths = Object.keys(parent.$__.populated).
|
|
334
|
+
filter(p => p.startsWith(arr[arrayPathSymbol] + '.'));
|
|
332
335
|
|
|
333
|
-
|
|
336
|
+
for (const path of populatedPaths) {
|
|
337
|
+
const remnant = path.slice((arr[arrayPathSymbol] + '.').length);
|
|
338
|
+
if (!Array.isArray(parent.$__.populated[path].value)) {
|
|
339
|
+
continue;
|
|
334
340
|
}
|
|
341
|
+
|
|
342
|
+
parent.$__.populated[path].value = arr.map(val => val.populated(remnant));
|
|
335
343
|
}
|
|
336
344
|
}
|
|
337
345
|
|
package/lib/utils.js
CHANGED
|
@@ -193,6 +193,11 @@ exports.clone = function clone(obj, options, isArrayChild) {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
if (isMongooseObject(obj)) {
|
|
196
|
+
// Single nested subdocs should apply getters later in `applyGetters()`
|
|
197
|
+
// when calling `toObject()`. See gh-7442, gh-8295
|
|
198
|
+
if (options && options._skipSingleNestedGetters && obj.$isSingleNested) {
|
|
199
|
+
options = Object.assign({}, options, { getters: false });
|
|
200
|
+
}
|
|
196
201
|
if (options && options.json && typeof obj.toJSON === 'function') {
|
|
197
202
|
return obj.toJSON(options);
|
|
198
203
|
}
|
|
@@ -232,6 +237,13 @@ exports.clone = function clone(obj, options, isArrayChild) {
|
|
|
232
237
|
return obj.clone();
|
|
233
238
|
}
|
|
234
239
|
|
|
240
|
+
// If we're cloning this object to go into a MongoDB command,
|
|
241
|
+
// and there's a `toBSON()` function, assume this object will be
|
|
242
|
+
// stored as a primitive in MongoDB and doesn't need to be cloned.
|
|
243
|
+
if (options && options.bson && typeof obj.toBSON === 'function') {
|
|
244
|
+
return obj;
|
|
245
|
+
}
|
|
246
|
+
|
|
235
247
|
if (obj.valueOf != null) {
|
|
236
248
|
return obj.valueOf();
|
|
237
249
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose",
|
|
3
3
|
"description": "Mongoose MongoDB ODM",
|
|
4
|
-
"version": "5.7.
|
|
4
|
+
"version": "5.7.12",
|
|
5
5
|
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mongodb",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"bson": "~1.1.1",
|
|
23
23
|
"kareem": "2.3.1",
|
|
24
|
-
"mongodb": "3.3.
|
|
24
|
+
"mongodb": "3.3.4",
|
|
25
25
|
"mongoose-legacy-pluralize": "1.0.2",
|
|
26
26
|
"mpath": "0.6.0",
|
|
27
27
|
"mquery": "3.2.2",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"lint": "eslint .",
|
|
74
74
|
"release": "git pull && git push origin master --tags && npm publish",
|
|
75
75
|
"release-legacy": "git pull origin 4.x && git push origin 4.x --tags && npm publish --tag legacy",
|
|
76
|
-
"test": "mocha --exit
|
|
76
|
+
"test": "mocha --exit",
|
|
77
77
|
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
|
78
78
|
},
|
|
79
79
|
"main": "./index.js",
|
|
@@ -89,6 +89,14 @@
|
|
|
89
89
|
},
|
|
90
90
|
"homepage": "https://mongoosejs.com",
|
|
91
91
|
"browser": "./browser.js",
|
|
92
|
+
"mocha": {
|
|
93
|
+
"extension": [
|
|
94
|
+
"test.js"
|
|
95
|
+
],
|
|
96
|
+
"watch-files": [
|
|
97
|
+
"test/**/*.js"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
92
100
|
"eslintConfig": {
|
|
93
101
|
"extends": [
|
|
94
102
|
"eslint:recommended"
|