mongoose 5.5.0 → 5.5.4
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 +43 -1
- package/lib/aggregate.js +16 -4
- package/lib/connection.js +7 -1
- package/lib/document.js +43 -36
- package/lib/drivers/node-mongodb-native/collection.js +16 -4
- package/lib/drivers/node-mongodb-native/index.js +1 -1
- package/lib/helpers/document/cleanModifiedSubpaths.js +3 -0
- package/lib/helpers/document/getEmbeddedDiscriminatorPath.js +5 -5
- package/lib/helpers/model/applyStaticHooks.js +3 -0
- package/lib/helpers/query/castUpdate.js +0 -2
- package/lib/helpers/schema/setParentPointers.js +5 -5
- package/lib/helpers/symbols.js +8 -11
- package/lib/helpers/update/applyTimestampsToChildren.js +22 -16
- package/lib/internal.js +1 -0
- package/lib/model.js +78 -24
- package/lib/query.js +76 -31
- package/lib/schema/array.js +50 -0
- package/lib/schema/documentarray.js +42 -26
- package/lib/schema.js +6 -5
- package/lib/schematype.js +32 -2
- package/lib/types/array.js +48 -24
- package/lib/types/documentarray.js +16 -13
- package/lib/types/embedded.js +1 -1
- package/lib/types/map.js +5 -0
- package/lib/types/subdocument.js +18 -1
- package/package.json +2 -2
package/lib/schematype.js
CHANGED
|
@@ -51,6 +51,21 @@ function SchemaType(path, options, instance) {
|
|
|
51
51
|
if (this[prop] && typeof this[prop] === 'function') {
|
|
52
52
|
// { unique: true, index: true }
|
|
53
53
|
if (prop === 'index' && this._index) {
|
|
54
|
+
if (options.index === false) {
|
|
55
|
+
const index = this._index;
|
|
56
|
+
if (typeof index === 'object' && index != null) {
|
|
57
|
+
if (index.unique) {
|
|
58
|
+
throw new Error('Path "' + this.path + '" may not have `index` ' +
|
|
59
|
+
'set to false and `unique` set to true');
|
|
60
|
+
}
|
|
61
|
+
if (index.sparse) {
|
|
62
|
+
throw new Error('Path "' + this.path + '" may not have `index` ' +
|
|
63
|
+
'set to false and `sparse` set to true');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this._index = false;
|
|
68
|
+
}
|
|
54
69
|
continue;
|
|
55
70
|
}
|
|
56
71
|
|
|
@@ -263,6 +278,14 @@ SchemaType.prototype.unique = function(bool) {
|
|
|
263
278
|
*/
|
|
264
279
|
|
|
265
280
|
SchemaType.prototype.text = function(bool) {
|
|
281
|
+
if (this._index === false) {
|
|
282
|
+
if (!bool) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
throw new Error('Path "' + this.path + '" may not have `index` set to ' +
|
|
286
|
+
'false and `text` set to true');
|
|
287
|
+
}
|
|
288
|
+
|
|
266
289
|
if (this._index === null || this._index === undefined ||
|
|
267
290
|
typeof this._index === 'boolean') {
|
|
268
291
|
this._index = {};
|
|
@@ -288,8 +311,15 @@ SchemaType.prototype.text = function(bool) {
|
|
|
288
311
|
*/
|
|
289
312
|
|
|
290
313
|
SchemaType.prototype.sparse = function(bool) {
|
|
291
|
-
if (this._index ===
|
|
292
|
-
|
|
314
|
+
if (this._index === false) {
|
|
315
|
+
if (!bool) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
throw new Error('Path "' + this.path + '" may not have `index` set to ' +
|
|
319
|
+
'false and `sparse` set to true');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (this._index == null || typeof this._index === 'boolean') {
|
|
293
323
|
this._index = {};
|
|
294
324
|
} else if (typeof this._index === 'string') {
|
|
295
325
|
this._index = {type: this._index};
|
package/lib/types/array.js
CHANGED
|
@@ -13,6 +13,8 @@ const internalToObjectOptions = require('../options').internalToObjectOptions;
|
|
|
13
13
|
const utils = require('../utils');
|
|
14
14
|
const util = require('util');
|
|
15
15
|
|
|
16
|
+
const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
|
|
17
|
+
const arraySchemaSymbol = require('../helpers/symbols').arraySchemaSymbol;
|
|
16
18
|
const isMongooseObject = utils.isMongooseObject;
|
|
17
19
|
|
|
18
20
|
/**
|
|
@@ -43,7 +45,7 @@ function MongooseArray(values, path, doc) {
|
|
|
43
45
|
arr.isMongooseArray = true;
|
|
44
46
|
arr.validators = [];
|
|
45
47
|
arr._atomics = {};
|
|
46
|
-
arr
|
|
48
|
+
arr[arraySchemaSymbol] = void 0;
|
|
47
49
|
if (util.inspect.custom) {
|
|
48
50
|
arr[util.inspect.custom] = arr.inspect;
|
|
49
51
|
}
|
|
@@ -53,8 +55,8 @@ function MongooseArray(values, path, doc) {
|
|
|
53
55
|
// RB Jun 17, 2015 updated to check for presence of expected paths instead
|
|
54
56
|
// to make more proof against unusual node environments
|
|
55
57
|
if (doc && doc instanceof Document) {
|
|
56
|
-
arr
|
|
57
|
-
arr
|
|
58
|
+
arr[arrayParentSymbol] = doc;
|
|
59
|
+
arr[arraySchemaSymbol] = doc.schema.path(path);
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
return arr;
|
|
@@ -77,15 +79,21 @@ MongooseArray.mixin = {
|
|
|
77
79
|
|
|
78
80
|
_atomics: undefined,
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* @property _parent
|
|
84
|
-
* @api private
|
|
85
|
-
* @memberOf MongooseArray
|
|
82
|
+
/*!
|
|
83
|
+
* ignore
|
|
86
84
|
*/
|
|
87
85
|
|
|
88
|
-
|
|
86
|
+
$parent: function() {
|
|
87
|
+
return this[arrayParentSymbol];
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
/*!
|
|
91
|
+
* ignore
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
$schema: function() {
|
|
95
|
+
return this[arraySchemaSymbol];
|
|
96
|
+
},
|
|
89
97
|
|
|
90
98
|
/**
|
|
91
99
|
* Casts a member based on this arrays schema.
|
|
@@ -101,8 +109,8 @@ MongooseArray.mixin = {
|
|
|
101
109
|
let populated = false;
|
|
102
110
|
let Model;
|
|
103
111
|
|
|
104
|
-
if (this
|
|
105
|
-
populated = this.
|
|
112
|
+
if (this[arrayParentSymbol]) {
|
|
113
|
+
populated = this[arrayParentSymbol].populated(this._path, true);
|
|
106
114
|
}
|
|
107
115
|
|
|
108
116
|
if (populated && value !== null && value !== undefined) {
|
|
@@ -123,10 +131,10 @@ MongooseArray.mixin = {
|
|
|
123
131
|
if (!isDisc) {
|
|
124
132
|
value = new Model(value);
|
|
125
133
|
}
|
|
126
|
-
return this.
|
|
134
|
+
return this[arraySchemaSymbol].caster.applySetters(value, this[arrayParentSymbol], true);
|
|
127
135
|
}
|
|
128
136
|
|
|
129
|
-
return this.
|
|
137
|
+
return this[arraySchemaSymbol].caster.applySetters(value, this[arrayParentSymbol], false);
|
|
130
138
|
},
|
|
131
139
|
|
|
132
140
|
/**
|
|
@@ -142,7 +150,7 @@ MongooseArray.mixin = {
|
|
|
142
150
|
*/
|
|
143
151
|
|
|
144
152
|
_markModified: function(elem, embeddedPath) {
|
|
145
|
-
const parent = this
|
|
153
|
+
const parent = this[arrayParentSymbol];
|
|
146
154
|
let dirtyPath;
|
|
147
155
|
|
|
148
156
|
if (parent) {
|
|
@@ -179,7 +187,7 @@ MongooseArray.mixin = {
|
|
|
179
187
|
// $set takes precedence over all other ops.
|
|
180
188
|
// mark entire array modified.
|
|
181
189
|
this._atomics = {$set: val};
|
|
182
|
-
cleanModifiedSubpaths(this
|
|
190
|
+
cleanModifiedSubpaths(this[arrayParentSymbol], this._path);
|
|
183
191
|
this._markModified();
|
|
184
192
|
return this;
|
|
185
193
|
}
|
|
@@ -189,7 +197,7 @@ MongooseArray.mixin = {
|
|
|
189
197
|
// reset pop/shift after save
|
|
190
198
|
if (op === '$pop' && !('$pop' in atomics)) {
|
|
191
199
|
const _this = this;
|
|
192
|
-
this.
|
|
200
|
+
this[arrayParentSymbol].once('save', function() {
|
|
193
201
|
_this._popped = _this._shifted = null;
|
|
194
202
|
});
|
|
195
203
|
}
|
|
@@ -322,7 +330,7 @@ MongooseArray.mixin = {
|
|
|
322
330
|
push: function() {
|
|
323
331
|
_checkManualPopulation(this, arguments);
|
|
324
332
|
let values = [].map.call(arguments, this._mapCast, this);
|
|
325
|
-
values = this.
|
|
333
|
+
values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol], undefined,
|
|
326
334
|
undefined, { skipDocumentArrayCast: true });
|
|
327
335
|
const ret = [].push.apply(this, values);
|
|
328
336
|
|
|
@@ -527,7 +535,7 @@ MongooseArray.mixin = {
|
|
|
527
535
|
|
|
528
536
|
pull: function() {
|
|
529
537
|
const values = [].map.call(arguments, this._cast, this);
|
|
530
|
-
const cur = this.
|
|
538
|
+
const cur = this[arrayParentSymbol].get(this._path);
|
|
531
539
|
let i = cur.length;
|
|
532
540
|
let mem;
|
|
533
541
|
|
|
@@ -559,7 +567,7 @@ MongooseArray.mixin = {
|
|
|
559
567
|
// `doc.children[1].name = 'test';` followed by
|
|
560
568
|
// `doc.children.remove(doc.children[0]);`. In this case we fall back
|
|
561
569
|
// to a `$set` on the whole array. See #3511
|
|
562
|
-
if (cleanModifiedSubpaths(this
|
|
570
|
+
if (cleanModifiedSubpaths(this[arrayParentSymbol], this._path) > 0) {
|
|
563
571
|
this._registerAtomic('$set', this);
|
|
564
572
|
}
|
|
565
573
|
|
|
@@ -613,7 +621,7 @@ MongooseArray.mixin = {
|
|
|
613
621
|
_checkManualPopulation(this, arguments);
|
|
614
622
|
|
|
615
623
|
let values = [].map.call(arguments, this._cast, this);
|
|
616
|
-
values = this.
|
|
624
|
+
values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol]);
|
|
617
625
|
[].unshift.apply(this, values);
|
|
618
626
|
this._registerAtomic('$set', this);
|
|
619
627
|
this._markModified();
|
|
@@ -659,7 +667,7 @@ MongooseArray.mixin = {
|
|
|
659
667
|
_checkManualPopulation(this, arguments);
|
|
660
668
|
|
|
661
669
|
let values = [].map.call(arguments, this._mapCast, this);
|
|
662
|
-
values = this.
|
|
670
|
+
values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol]);
|
|
663
671
|
const added = [];
|
|
664
672
|
let type = '';
|
|
665
673
|
if (values[0] instanceof EmbeddedDocument) {
|
|
@@ -787,6 +795,20 @@ MongooseArray.mixin = {
|
|
|
787
795
|
}
|
|
788
796
|
}
|
|
789
797
|
return -1;
|
|
798
|
+
},
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Return whether or not the `obj` is included in the array.
|
|
802
|
+
*
|
|
803
|
+
* @param {Object} obj the item to check
|
|
804
|
+
* @return {Boolean}
|
|
805
|
+
* @api public
|
|
806
|
+
* @method includes
|
|
807
|
+
* @memberOf MongooseArray
|
|
808
|
+
*/
|
|
809
|
+
|
|
810
|
+
includes: function includes(obj) {
|
|
811
|
+
return this.indexOf(obj) !== -1;
|
|
790
812
|
}
|
|
791
813
|
};
|
|
792
814
|
|
|
@@ -831,11 +853,13 @@ function _isAllSubdocs(docs, ref) {
|
|
|
831
853
|
*/
|
|
832
854
|
|
|
833
855
|
function _checkManualPopulation(arr, docs) {
|
|
834
|
-
const ref =
|
|
856
|
+
const ref = arr == null ?
|
|
857
|
+
null :
|
|
858
|
+
get(arr[arraySchemaSymbol], 'caster.options.ref', null);
|
|
835
859
|
if (arr.length === 0 &&
|
|
836
860
|
docs.length > 0) {
|
|
837
861
|
if (_isAllSubdocs(docs, ref)) {
|
|
838
|
-
arr.
|
|
862
|
+
arr[arrayParentSymbol].populated(arr._path, [], { model: docs[0].constructor });
|
|
839
863
|
}
|
|
840
864
|
}
|
|
841
865
|
}
|
|
@@ -8,12 +8,13 @@ const Document = require('../document');
|
|
|
8
8
|
const MongooseArray = require('./array');
|
|
9
9
|
const ObjectId = require('./objectid');
|
|
10
10
|
const castObjectId = require('../cast/objectid');
|
|
11
|
-
const get = require('../helpers/get');
|
|
12
11
|
const getDiscriminatorByValue = require('../queryhelpers').getDiscriminatorByValue;
|
|
13
12
|
const internalToObjectOptions = require('../options').internalToObjectOptions;
|
|
14
13
|
const util = require('util');
|
|
15
14
|
const utils = require('../utils');
|
|
16
15
|
|
|
16
|
+
const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
|
|
17
|
+
const arraySchemaSymbol = require('../helpers/symbols').arraySchemaSymbol;
|
|
17
18
|
const documentArrayParent = require('../helpers/symbols').documentArrayParent;
|
|
18
19
|
|
|
19
20
|
/*!
|
|
@@ -49,14 +50,14 @@ function MongooseDocumentArray(values, path, doc) {
|
|
|
49
50
|
isMongooseDocumentArray: true,
|
|
50
51
|
validators: [],
|
|
51
52
|
_atomics: {},
|
|
52
|
-
|
|
53
|
+
[arraySchemaSymbol]: void 0,
|
|
53
54
|
_handlers: void 0
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
if (Array.isArray(values)) {
|
|
57
58
|
if (values instanceof CoreMongooseArray &&
|
|
58
59
|
values._path === path &&
|
|
59
|
-
values
|
|
60
|
+
values[arrayParentSymbol] === doc) {
|
|
60
61
|
props._atomics = Object.assign({}, values._atomics);
|
|
61
62
|
}
|
|
62
63
|
values.forEach(v => {
|
|
@@ -93,22 +94,24 @@ function MongooseDocumentArray(values, path, doc) {
|
|
|
93
94
|
// RB Jun 17, 2015 updated to check for presence of expected paths instead
|
|
94
95
|
// to make more proof against unusual node environments
|
|
95
96
|
if (doc && doc instanceof Document) {
|
|
96
|
-
arr
|
|
97
|
-
arr
|
|
97
|
+
arr[arrayParentSymbol] = doc;
|
|
98
|
+
arr[arraySchemaSymbol] = doc.schema.path(path);
|
|
98
99
|
|
|
99
100
|
// `schema.path()` doesn't drill into nested arrays properly yet, see
|
|
100
101
|
// gh-6398, gh-6602. This is a workaround because nested arrays are
|
|
101
102
|
// always plain non-document arrays, so once you get to a document array
|
|
102
103
|
// nesting is done. Matryoshka code.
|
|
103
|
-
while (
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
while (arr != null &&
|
|
105
|
+
arr[arraySchemaSymbol] != null &&
|
|
106
|
+
arr[arraySchemaSymbol].$isMongooseArray &&
|
|
107
|
+
!arr[arraySchemaSymbol].$isMongooseDocumentArray) {
|
|
108
|
+
arr[arraySchemaSymbol] = arr[arraySchemaSymbol].casterConstructor;
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
// Tricky but this may be a document array embedded in a normal array,
|
|
109
112
|
// in which case `path` would point to the embedded array. See #6405, #6398
|
|
110
|
-
if (arr
|
|
111
|
-
arr
|
|
113
|
+
if (arr[arraySchemaSymbol] && !arr[arraySchemaSymbol].$isMongooseDocumentArray) {
|
|
114
|
+
arr[arraySchemaSymbol] = arr[arraySchemaSymbol].casterConstructor;
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
arr._handlers = {
|
|
@@ -144,7 +147,7 @@ MongooseDocumentArray.mixin = {
|
|
|
144
147
|
*/
|
|
145
148
|
|
|
146
149
|
_cast: function(value, index) {
|
|
147
|
-
let Constructor = this.
|
|
150
|
+
let Constructor = this[arraySchemaSymbol].casterConstructor;
|
|
148
151
|
const isInstance = Constructor.$isMongooseDocumentArray ?
|
|
149
152
|
value && value.isMongooseDocumentArray :
|
|
150
153
|
value instanceof Constructor;
|
|
@@ -153,7 +156,7 @@ MongooseDocumentArray.mixin = {
|
|
|
153
156
|
(value && value.constructor && value.constructor.baseCasterConstructor === Constructor)) {
|
|
154
157
|
if (!(value[documentArrayParent] && value.__parentArray)) {
|
|
155
158
|
// value may have been created using array.create()
|
|
156
|
-
value[documentArrayParent] = this
|
|
159
|
+
value[documentArrayParent] = this[arrayParentSymbol];
|
|
157
160
|
value.__parentArray = this;
|
|
158
161
|
}
|
|
159
162
|
value.$setIndex(index);
|
|
@@ -293,7 +296,7 @@ MongooseDocumentArray.mixin = {
|
|
|
293
296
|
*/
|
|
294
297
|
|
|
295
298
|
create: function(obj) {
|
|
296
|
-
let Constructor = this.
|
|
299
|
+
let Constructor = this[arraySchemaSymbol].casterConstructor;
|
|
297
300
|
if (obj &&
|
|
298
301
|
Constructor.discriminators &&
|
|
299
302
|
Constructor.schema &&
|
package/lib/types/embedded.js
CHANGED
|
@@ -30,7 +30,7 @@ const validatorErrorSymbol = require('../helpers/symbols').validatorErrorSymbol;
|
|
|
30
30
|
function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
|
|
31
31
|
if (parentArr) {
|
|
32
32
|
this.__parentArray = parentArr;
|
|
33
|
-
this[documentArrayParent] = parentArr
|
|
33
|
+
this[documentArrayParent] = parentArr.$parent();
|
|
34
34
|
} else {
|
|
35
35
|
this.__parentArray = undefined;
|
|
36
36
|
this[documentArrayParent] = undefined;
|
package/lib/types/map.js
CHANGED
package/lib/types/subdocument.js
CHANGED
|
@@ -18,13 +18,30 @@ module.exports = Subdocument;
|
|
|
18
18
|
|
|
19
19
|
function Subdocument(value, fields, parent, skipId, options) {
|
|
20
20
|
this.$isSingleNested = true;
|
|
21
|
+
|
|
22
|
+
const hasPriorDoc = options != null && options.priorDoc;
|
|
23
|
+
let initedPaths = null;
|
|
24
|
+
if (hasPriorDoc) {
|
|
25
|
+
this._doc = Object.assign({}, options.priorDoc._doc);
|
|
26
|
+
delete this._doc[this.schema.options.discriminatorKey];
|
|
27
|
+
initedPaths = Object.keys(options.priorDoc._doc || {}).
|
|
28
|
+
filter(key => key !== this.schema.options.discriminatorKey);
|
|
29
|
+
}
|
|
21
30
|
if (parent != null) {
|
|
22
31
|
// If setting a nested path, should copy isNew from parent re: gh-7048
|
|
23
32
|
options = Object.assign({}, options, { isNew: parent.isNew });
|
|
24
33
|
}
|
|
25
34
|
Document.call(this, value, fields, skipId, options);
|
|
26
35
|
|
|
27
|
-
|
|
36
|
+
if (hasPriorDoc) {
|
|
37
|
+
for (const key of initedPaths) {
|
|
38
|
+
if (!this.$__.activePaths.states.modify[key] &&
|
|
39
|
+
!this.$__.activePaths.states.default[key] &&
|
|
40
|
+
!this.$__.$setCalled.has(key)) {
|
|
41
|
+
delete this._doc[key];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
28
45
|
}
|
|
29
46
|
|
|
30
47
|
Subdocument.prototype = Object.create(Document.prototype);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose",
|
|
3
3
|
"description": "Mongoose MongoDB ODM",
|
|
4
|
-
"version": "5.5.
|
|
4
|
+
"version": "5.5.4",
|
|
5
5
|
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mongodb",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"mongodb": "3.2.2",
|
|
26
26
|
"mongodb-core": "3.2.2",
|
|
27
27
|
"mongoose-legacy-pluralize": "1.0.2",
|
|
28
|
-
"mpath": "0.5.
|
|
28
|
+
"mpath": "0.5.2",
|
|
29
29
|
"mquery": "3.2.0",
|
|
30
30
|
"ms": "2.1.1",
|
|
31
31
|
"regexp-clone": "0.0.1",
|