mongoose 5.0.17 → 5.1.2
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/.travis.yml +4 -3
- package/History.md +61 -0
- package/lib/aggregate.js +15 -4
- package/lib/connection.js +12 -0
- package/lib/document.js +79 -18
- package/lib/drivers/browser/objectid.js +12 -0
- package/lib/drivers/node-mongodb-native/collection.js +46 -35
- package/lib/error/version.js +4 -2
- package/lib/index.js +12 -7
- package/lib/internal.js +1 -0
- package/lib/model.js +329 -96
- package/lib/plugins/idGetter.js +0 -12
- package/lib/plugins/saveSubdocs.js +1 -1
- package/lib/query.js +202 -109
- package/lib/queryhelpers.js +59 -32
- package/lib/schema/array.js +6 -3
- package/lib/schema/date.js +5 -2
- package/lib/schema/decimal128.js +4 -0
- package/lib/schema/embedded.js +15 -9
- package/lib/schema/index.js +2 -0
- package/lib/schema/map.js +29 -0
- package/lib/schema/objectid.js +0 -20
- package/lib/schema.js +49 -9
- package/lib/schematype.js +19 -1
- package/lib/services/model/applyHooks.js +22 -2
- package/lib/services/model/applyMethods.js +14 -4
- package/lib/services/populate/getVirtual.js +4 -0
- package/lib/services/query/castUpdate.js +1 -1
- package/lib/services/query/completeMany.js +47 -0
- package/lib/types/buffer.js +1 -1
- package/lib/types/documentarray.js +16 -2
- package/lib/types/embedded.js +33 -1
- package/lib/types/index.js +2 -0
- package/lib/types/map.js +149 -0
- package/lib/types/objectid.js +12 -0
- package/lib/types/subdocument.js +30 -1
- package/lib/utils.js +49 -6
- package/migrating_to_5.md +1 -1
- package/package.json +5 -5
package/lib/types/map.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*!
|
|
4
|
+
* ignore
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class MongooseMap extends Map {
|
|
8
|
+
constructor(v, path, doc, schemaType) {
|
|
9
|
+
if (v != null && v.constructor.name === 'Object') {
|
|
10
|
+
v = Object.keys(v).reduce((arr, key) => arr.concat([[key, v[key]]]), []);
|
|
11
|
+
}
|
|
12
|
+
super(v);
|
|
13
|
+
|
|
14
|
+
this.$__parent = doc;
|
|
15
|
+
this.$__path = path;
|
|
16
|
+
this.$__schemaType = schemaType;
|
|
17
|
+
|
|
18
|
+
this.$__runDeferred();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
$init(key, value) {
|
|
22
|
+
if (key.startsWith('$')) {
|
|
23
|
+
throw new Error('Mongoose maps do not support keys that start with ' +
|
|
24
|
+
'`$`, got "' + key + '"');
|
|
25
|
+
}
|
|
26
|
+
if (key.indexOf('.') !== -1) {
|
|
27
|
+
throw new Error('Mongoose maps do not support keys that contain `.`, ' +
|
|
28
|
+
'got "' + key + '"');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
super.set(key, value);
|
|
32
|
+
|
|
33
|
+
if (value != null && value.$isSingleNested) {
|
|
34
|
+
value.$basePath = this.$__path + '.' + key;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set(key, value) {
|
|
39
|
+
if (key.startsWith('$')) {
|
|
40
|
+
throw new Error('Mongoose maps do not support keys that start with ' +
|
|
41
|
+
'`$`, got "' + key + '"');
|
|
42
|
+
}
|
|
43
|
+
if (key.indexOf('.') !== -1) {
|
|
44
|
+
throw new Error('Mongoose maps do not support keys that contain `.`, ' +
|
|
45
|
+
'got "' + key + '"');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Weird, but because you can't assign to `this` before calling `super()`
|
|
49
|
+
// you can't get access to `$__schemaType` to cast in the initial call to
|
|
50
|
+
// `set()` from the `super()` constructor.
|
|
51
|
+
|
|
52
|
+
if (this.$__schemaType == null) {
|
|
53
|
+
this.$__deferred = this.$__deferred || [];
|
|
54
|
+
this.$__deferred.push({ key: key, value: value });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const fullPath = this.$__path + '.' + key;
|
|
59
|
+
const populated = this.$__parent != null && this.$__parent.$__ ?
|
|
60
|
+
this.$__parent.populated(fullPath) || this.$__parent.populated(this.$__path) :
|
|
61
|
+
null;
|
|
62
|
+
|
|
63
|
+
if (populated != null) {
|
|
64
|
+
if (value.$__ == null) {
|
|
65
|
+
value = new populated.options.model(value);
|
|
66
|
+
}
|
|
67
|
+
value.$__.wasPopulated = true;
|
|
68
|
+
} else {
|
|
69
|
+
try {
|
|
70
|
+
value = this.$__schemaType.
|
|
71
|
+
applySetters(value, this.$__parent, false, this.get(key));
|
|
72
|
+
} catch (error) {
|
|
73
|
+
this.$__parent.invalidate(fullPath, error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
super.set(key, value);
|
|
79
|
+
|
|
80
|
+
if (value != null && value.$isSingleNested) {
|
|
81
|
+
value.$basePath = this.$__path + '.' + key;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (this.$__parent != null && this.$__parent.$__) {
|
|
85
|
+
this.$__parent.markModified(this.$__path + '.' + key);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
toBSON() {
|
|
90
|
+
return new Map(this);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
toJSON() {
|
|
94
|
+
let ret = {};
|
|
95
|
+
const keys = this.keys();
|
|
96
|
+
for (let key of keys) {
|
|
97
|
+
ret[key] = this.get(key);
|
|
98
|
+
}
|
|
99
|
+
return ret;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
inspect() {
|
|
103
|
+
return new Map(this);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
$__runDeferred() {
|
|
107
|
+
if (!this.$__deferred) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
for (let i = 0; i < this.$__deferred.length; ++i) {
|
|
111
|
+
this.set(this.$__deferred[i].key, this.$__deferred[i].value);
|
|
112
|
+
}
|
|
113
|
+
this.$__deferred = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
Object.defineProperty(MongooseMap.prototype, '$__parent', {
|
|
118
|
+
enumerable: false,
|
|
119
|
+
writable: true,
|
|
120
|
+
configurable: false
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
Object.defineProperty(MongooseMap.prototype, '$__path', {
|
|
124
|
+
enumerable: false,
|
|
125
|
+
writable: true,
|
|
126
|
+
configurable: false
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
Object.defineProperty(MongooseMap.prototype, '$__schemaType', {
|
|
130
|
+
enumerable: false,
|
|
131
|
+
writable: true,
|
|
132
|
+
configurable: false
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
Object.defineProperty(MongooseMap.prototype, '$isMongooseMap', {
|
|
136
|
+
enumerable: false,
|
|
137
|
+
writable: false,
|
|
138
|
+
configurable: false,
|
|
139
|
+
value: true
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
Object.defineProperty(MongooseMap.prototype, '$__deferredCalls', {
|
|
143
|
+
enumerable: false,
|
|
144
|
+
writable: false,
|
|
145
|
+
configurable: false,
|
|
146
|
+
value: true
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
module.exports = MongooseMap;
|
package/lib/types/objectid.js
CHANGED
|
@@ -10,4 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
var ObjectId = require('../drivers').ObjectId;
|
|
12
12
|
|
|
13
|
+
/*!
|
|
14
|
+
* Getter for convenience with populate, see gh-6115
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
Object.defineProperty(ObjectId.prototype, '_id', {
|
|
18
|
+
enumerable: false,
|
|
19
|
+
configurable: true,
|
|
20
|
+
get: function() {
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
13
25
|
module.exports = ObjectId;
|
package/lib/types/subdocument.js
CHANGED
|
@@ -36,7 +36,20 @@ Subdocument.prototype.toBSON = function() {
|
|
|
36
36
|
* @api private
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
|
-
Subdocument.prototype.save = function(fn) {
|
|
39
|
+
Subdocument.prototype.save = function(options, fn) {
|
|
40
|
+
if (typeof options === 'function') {
|
|
41
|
+
fn = options;
|
|
42
|
+
options = {};
|
|
43
|
+
}
|
|
44
|
+
options = options || {};
|
|
45
|
+
|
|
46
|
+
if (!options.suppressWarning) {
|
|
47
|
+
console.warn('mongoose: calling `save()` on a subdoc does **not** save ' +
|
|
48
|
+
'the document to MongoDB, it only runs save middleware. ' +
|
|
49
|
+
'Use `subdoc.save({ suppressWarning: true })` to hide this warning ' +
|
|
50
|
+
'if you\'re sure this behavior is right for your app.');
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
return utils.promiseOrCallback(fn, cb => {
|
|
41
54
|
this.$__save(cb);
|
|
42
55
|
});
|
|
@@ -67,6 +80,7 @@ Subdocument.prototype.$isValid = function(path) {
|
|
|
67
80
|
|
|
68
81
|
Subdocument.prototype.markModified = function(path) {
|
|
69
82
|
Document.prototype.markModified.call(this, path);
|
|
83
|
+
|
|
70
84
|
if (this.$parent && this.$basePath) {
|
|
71
85
|
if (this.$parent.isDirectModified(this.$basePath)) {
|
|
72
86
|
return;
|
|
@@ -82,6 +96,10 @@ Subdocument.prototype.$markValid = function(path) {
|
|
|
82
96
|
}
|
|
83
97
|
};
|
|
84
98
|
|
|
99
|
+
/*!
|
|
100
|
+
* ignore
|
|
101
|
+
*/
|
|
102
|
+
|
|
85
103
|
Subdocument.prototype.invalidate = function(path, err, val) {
|
|
86
104
|
// Hack: array subdocuments' validationError is equal to the owner doc's,
|
|
87
105
|
// so validating an array subdoc gives the top-level doc back. Temporary
|
|
@@ -97,6 +115,17 @@ Subdocument.prototype.invalidate = function(path, err, val) {
|
|
|
97
115
|
}
|
|
98
116
|
};
|
|
99
117
|
|
|
118
|
+
/*!
|
|
119
|
+
* ignore
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
Subdocument.prototype.$ignore = function(path) {
|
|
123
|
+
Document.prototype.$ignore.call(this, path);
|
|
124
|
+
if (this.$parent && this.$basePath) {
|
|
125
|
+
this.$parent.$ignore([this.$basePath, path].join('.'));
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
100
129
|
/**
|
|
101
130
|
* Returns the top level document of this sub-document.
|
|
102
131
|
*
|
package/lib/utils.js
CHANGED
|
@@ -137,6 +137,17 @@ exports.deepEqual = function deepEqual(a, b) {
|
|
|
137
137
|
return true;
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
+
/*!
|
|
141
|
+
* Get the last element of an array
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
exports.last = function(arr) {
|
|
145
|
+
if (arr.length > 0) {
|
|
146
|
+
return arr[arr.length - 1];
|
|
147
|
+
}
|
|
148
|
+
return void 0;
|
|
149
|
+
};
|
|
150
|
+
|
|
140
151
|
/*!
|
|
141
152
|
* Object clone with Mongoose natives support.
|
|
142
153
|
*
|
|
@@ -446,9 +457,11 @@ exports.isMongooseObject = function(v) {
|
|
|
446
457
|
MongooseArray || (MongooseArray = require('./types').Array);
|
|
447
458
|
MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
|
|
448
459
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
460
|
+
if (v == null) {
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
return v.$__ != null || v.isMongooseArray || v.isMongooseBuffer;
|
|
452
465
|
};
|
|
453
466
|
var isMongooseObject = exports.isMongooseObject;
|
|
454
467
|
|
|
@@ -508,6 +521,24 @@ exports.populate = function populate(path, select, model, match, options, subPop
|
|
|
508
521
|
// necessary to keep backward compatibility (select could be
|
|
509
522
|
// an array, string, or object literal).
|
|
510
523
|
|
|
524
|
+
function makeSingles(arr) {
|
|
525
|
+
let ret = [];
|
|
526
|
+
arr.forEach(function(obj) {
|
|
527
|
+
if (/[\s]/.test(obj.path)) {
|
|
528
|
+
let paths = obj.path.split(' ');
|
|
529
|
+
paths.forEach(function(p) {
|
|
530
|
+
let copy = Object.assign({}, obj);
|
|
531
|
+
copy.path = p;
|
|
532
|
+
ret.push(copy);
|
|
533
|
+
});
|
|
534
|
+
} else {
|
|
535
|
+
ret.push(obj);
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
return ret;
|
|
540
|
+
}
|
|
541
|
+
|
|
511
542
|
// might have passed an object specifying all arguments
|
|
512
543
|
if (arguments.length === 1) {
|
|
513
544
|
if (path instanceof PopulateOptions) {
|
|
@@ -515,8 +546,20 @@ exports.populate = function populate(path, select, model, match, options, subPop
|
|
|
515
546
|
}
|
|
516
547
|
|
|
517
548
|
if (Array.isArray(path)) {
|
|
518
|
-
|
|
519
|
-
|
|
549
|
+
let singles = makeSingles(path);
|
|
550
|
+
return singles.map(function(o) {
|
|
551
|
+
if (o.populate && !o.match) {
|
|
552
|
+
return exports.populate(
|
|
553
|
+
o.path,
|
|
554
|
+
o.select,
|
|
555
|
+
o.model,
|
|
556
|
+
o.match,
|
|
557
|
+
o.options,
|
|
558
|
+
o.populate)[0];
|
|
559
|
+
} else {
|
|
560
|
+
return exports.populate(o)[0];
|
|
561
|
+
}
|
|
562
|
+
|
|
520
563
|
});
|
|
521
564
|
}
|
|
522
565
|
|
|
@@ -690,7 +733,7 @@ exports.array.unique = function(arr) {
|
|
|
690
733
|
var ret = [];
|
|
691
734
|
var length = arr.length;
|
|
692
735
|
for (var i = 0; i < length; ++i) {
|
|
693
|
-
if (typeof arr[i] === 'number' || typeof arr[i] === 'string') {
|
|
736
|
+
if (typeof arr[i] === 'number' || typeof arr[i] === 'string' || arr[i] == null) {
|
|
694
737
|
if (primitives[arr[i]]) {
|
|
695
738
|
continue;
|
|
696
739
|
}
|
package/migrating_to_5.md
CHANGED
|
@@ -100,7 +100,7 @@ const cursorWithOptions = MyModel.
|
|
|
100
100
|
|
|
101
101
|
### geoNear
|
|
102
102
|
|
|
103
|
-
`Model.geoNear()` has been removed because the [MongoDB driver no longer supports it](https://github.com/mongodb/node-mongodb-native/blob/
|
|
103
|
+
`Model.geoNear()` has been removed because the [MongoDB driver no longer supports it](https://github.com/mongodb/node-mongodb-native/blob/master/CHANGES_3.0.0.md#geonear-command-helper)
|
|
104
104
|
|
|
105
105
|
### Required URI encoding of connection strings
|
|
106
106
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose",
|
|
3
3
|
"description": "Mongoose MongoDB ODM",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.1.2",
|
|
5
5
|
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mongodb",
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"async": "2.1.4",
|
|
23
|
-
"bson": "~1.0.
|
|
24
|
-
"kareem": "2.0
|
|
23
|
+
"bson": "~1.0.5",
|
|
24
|
+
"kareem": "2.1.0",
|
|
25
25
|
"lodash.get": "4.4.2",
|
|
26
|
-
"mongodb": "3.0.
|
|
26
|
+
"mongodb": "3.0.8",
|
|
27
27
|
"mongoose-legacy-pluralize": "1.0.2",
|
|
28
28
|
"mpath": "0.4.1",
|
|
29
29
|
"mquery": "3.0.0",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"sliced": "1.0.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"acquit": "0.
|
|
35
|
+
"acquit": "0.6.3",
|
|
36
36
|
"acquit-ignore": "0.0.3",
|
|
37
37
|
"benchmark": "2.1.2",
|
|
38
38
|
"bluebird": "3.5.0",
|