mongoose 5.0.2 → 5.0.6
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/CONTRIBUTING.md +29 -0
- package/History.md +46 -0
- package/lib/aggregate.js +2 -2
- package/lib/cast.js +6 -2
- package/lib/collection.js +6 -3
- package/lib/connection.js +10 -7
- package/lib/document.js +128 -84
- package/lib/drivers/node-mongodb-native/collection.js +1 -1
- package/lib/index.js +1 -0
- package/lib/model.js +11 -11
- package/lib/schema/array.js +18 -0
- package/lib/schema/objectid.js +8 -7
- package/lib/schema.js +8 -4
- package/lib/schematype.js +2 -2
- package/lib/services/model/discriminator.js +1 -1
- package/lib/services/projection/isExclusive.js +28 -0
- package/lib/services/query/castUpdate.js +14 -11
- package/lib/types/array.js +8 -4
- package/lib/types/embedded.js +2 -2
- package/lib/types/subdocument.js +1 -1
- package/lib/utils.js +27 -8
- package/package.json +5 -5
- package/docs.html +0 -413
- package/test.js +0 -1
package/CONTRIBUTING.md
CHANGED
|
@@ -60,3 +60,32 @@ Visit `http://localhost:8088` and you should see the docs with your local change
|
|
|
60
60
|
### Plugins website
|
|
61
61
|
|
|
62
62
|
The [plugins](http://plugins.mongoosejs.io/) site is also an [open source project](https://github.com/vkarpov15/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well!
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## Financial contributions
|
|
66
|
+
|
|
67
|
+
We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/mongoose).
|
|
68
|
+
Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## Credits
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Contributors
|
|
75
|
+
|
|
76
|
+
Thank you to all the people who have already contributed to mongoose!
|
|
77
|
+
<a href="graphs/contributors"><img src="https://opencollective.com/mongoose/contributors.svg?width=890" /></a>
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
### Backers
|
|
81
|
+
|
|
82
|
+
Thank you to all our backers! [[Become a backer](https://opencollective.com/mongoose#backer)]
|
|
83
|
+
|
|
84
|
+
<a href="https://opencollective.com/mongoose#backers" target="_blank"><img src="https://opencollective.com/mongoose/backers.svg?width=890"></a>
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### Sponsors
|
|
88
|
+
|
|
89
|
+
Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/mongoose#sponsor))
|
|
90
|
+
|
|
91
|
+
<a href="https://mixmax.com" target="_blank"><img src="http://mongoosejs.com/docs/images/mixmax.png"></a>
|
package/History.md
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
+
5.0.6 / 2018-02-15
|
|
2
|
+
==================
|
|
3
|
+
* refactor(query.castUpdate): avoid creating error until necessary #6137
|
|
4
|
+
* docs(api): fix missing api docs #6136 [lineus](https://github.com/lineus)
|
|
5
|
+
* fix(schema): copy virtuals when using `clone()` #6133
|
|
6
|
+
* fix(update): avoid digging into buffers with upsert and replaceOne #6124
|
|
7
|
+
* fix(schema): support `enum` on arrays of strings #6102
|
|
8
|
+
* fix(update): cast `$addToSet: [1, 2]` -> `$addToSet: { $each: [1, 2] }` #6086
|
|
9
|
+
|
|
10
|
+
5.0.5 / 2018-02-13
|
|
11
|
+
==================
|
|
12
|
+
* docs: make > show up correctly in API docs #6114
|
|
13
|
+
* fix(query): support `where()` overwriting primitive with object #6097
|
|
14
|
+
* fix(schematype): don't run internal `resetId` setter on queries with _id #6093
|
|
15
|
+
* fix(discriminator): don't copy `discriminators` property from base schema #6064
|
|
16
|
+
* fix(utils): respect `valueOf()` when merging object for update #6059
|
|
17
|
+
* docs(validation): fix typo 'maxLength' #4720
|
|
18
|
+
* fix(document): apply defaults after setting initial value so default functions don't see empty doc #3781
|
|
19
|
+
|
|
20
|
+
5.0.4 / 2018-02-08
|
|
21
|
+
==================
|
|
22
|
+
* docs: add lambda guide #6107
|
|
23
|
+
* fix(connection): add `dbName` option to work around `mongodb+srv` not supporting db name in URI #6106
|
|
24
|
+
* fix(schematype): fix regexp typo in ObjectId #6098 [JoshuaWise](https://github.com/JoshuaWise)
|
|
25
|
+
* perf(document): re-use the modifiedPaths list #6092 [tarun1793](https://github.com/tarun1793)
|
|
26
|
+
* fix: use console.info() instead of console.error() for debug output #6088 [yuristsepaniuk](https://github.com/yuristsepaniuk)
|
|
27
|
+
* docs(validation): clean up runValidators and isAsync options docs for 5.x #6083
|
|
28
|
+
* docs(model): use array instead of spread consistently for aggregate() #6070
|
|
29
|
+
* fix(schema): make aliases handle mongoose-lean-virtuals #6069
|
|
30
|
+
* docs(layout): add link to subdocs guide #6056
|
|
31
|
+
* fix(query): make strictQuery: true strip out fields that aren't in the schema #6032
|
|
32
|
+
* docs(guide): add notes for `strictQuery` option #6032
|
|
33
|
+
|
|
34
|
+
4.13.11 / 2018-02-07
|
|
35
|
+
====================
|
|
36
|
+
* docs: fix links in 4.x docs #6081
|
|
37
|
+
* chore: add release script that uses --tag for npm publish for 4.x releases #6063
|
|
38
|
+
|
|
39
|
+
5.0.3 / 2018-01-31
|
|
40
|
+
==================
|
|
41
|
+
* fix: consistently use process.nextTick() to avoid sinon.useFakeTimers() causing ops to hang #6074
|
|
42
|
+
* docs(aggregate): fix typo #6072 [adursun](https://github.com/adursun)
|
|
43
|
+
* chore: add return type to `mongoose.model()` docs [bryant1410](https://github.com/bryant1410)
|
|
44
|
+
* fix(document): depopulate push()-ed docs when saving #6048
|
|
45
|
+
* fix: upgrade mongodb -> 3.0.2 #6019
|
|
46
|
+
|
|
1
47
|
5.0.2 / 2018-01-28
|
|
2
48
|
==================
|
|
3
49
|
* fix(schema): do not overwrite default values in schema when nested timestamps are provided #6024 [cdeveas](https://github.com/cdeveas)
|
package/lib/aggregate.js
CHANGED
|
@@ -20,7 +20,7 @@ var read = Query.prototype.read;
|
|
|
20
20
|
* ]);
|
|
21
21
|
*
|
|
22
22
|
* Model.
|
|
23
|
-
* aggregate({ $match: { age: { $gte: 21 }}}).
|
|
23
|
+
* aggregate([{ $match: { age: { $gte: 21 }}}]).
|
|
24
24
|
* unwind('tags').
|
|
25
25
|
* exec(callback);
|
|
26
26
|
*
|
|
@@ -392,7 +392,7 @@ Aggregate.prototype.graphLookup = function(options) {
|
|
|
392
392
|
};
|
|
393
393
|
|
|
394
394
|
/**
|
|
395
|
-
*
|
|
395
|
+
* Appends new custom $sample operator(s) to this aggregate pipeline.
|
|
396
396
|
*
|
|
397
397
|
* ####Examples:
|
|
398
398
|
*
|
package/lib/cast.js
CHANGED
|
@@ -33,6 +33,8 @@ module.exports = function cast(schema, obj, options, context) {
|
|
|
33
33
|
var type;
|
|
34
34
|
var val;
|
|
35
35
|
|
|
36
|
+
options = options || {};
|
|
37
|
+
|
|
36
38
|
while (i--) {
|
|
37
39
|
path = paths[i];
|
|
38
40
|
val = obj[path];
|
|
@@ -192,15 +194,17 @@ module.exports = function cast(schema, obj, options, context) {
|
|
|
192
194
|
}
|
|
193
195
|
}
|
|
194
196
|
|
|
195
|
-
if (options
|
|
197
|
+
if (options.upsert && options.strict && !schema.nested[path]) {
|
|
196
198
|
if (options.strict === 'throw') {
|
|
197
199
|
throw new StrictModeError(path);
|
|
198
200
|
}
|
|
199
201
|
throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
|
|
200
202
|
'schema, strict mode is `true`, and upsert is `true`.');
|
|
201
|
-
} else if (options
|
|
203
|
+
} else if (options.strictQuery === 'throw') {
|
|
202
204
|
throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
|
|
203
205
|
'schema and strictQuery is true.');
|
|
206
|
+
} else if (options.strictQuery) {
|
|
207
|
+
delete obj[path];
|
|
204
208
|
}
|
|
205
209
|
} else if (val === null || val === undefined) {
|
|
206
210
|
obj[path] = null;
|
package/lib/collection.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
1
3
|
/*!
|
|
2
4
|
* Module dependencies.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
const EventEmitter = require('events').EventEmitter;
|
|
8
|
+
const STATES = require('./connectionstate');
|
|
9
|
+
const utils = require('./utils');
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Abstract Collection constructor
|
|
@@ -81,7 +84,7 @@ Collection.prototype.conn;
|
|
|
81
84
|
Collection.prototype.onOpen = function() {
|
|
82
85
|
this.buffer = false;
|
|
83
86
|
var _this = this;
|
|
84
|
-
|
|
87
|
+
utils.immediate(function() {
|
|
85
88
|
_this.doQueue();
|
|
86
89
|
});
|
|
87
90
|
};
|
package/lib/connection.js
CHANGED
|
@@ -286,12 +286,12 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
286
286
|
options = null;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
const Promise = PromiseProvider.get();
|
|
290
|
+
const _this = this;
|
|
291
291
|
|
|
292
292
|
if (options) {
|
|
293
293
|
options = utils.clone(options);
|
|
294
|
-
|
|
294
|
+
const autoIndex = options.config && options.config.autoIndex != null ?
|
|
295
295
|
options.config.autoIndex :
|
|
296
296
|
options.autoIndex;
|
|
297
297
|
if (autoIndex != null) {
|
|
@@ -325,8 +325,10 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
this._connectionOptions = options;
|
|
328
|
+
let dbName = options.dbName;
|
|
329
|
+
delete options.dbName;
|
|
328
330
|
|
|
329
|
-
|
|
331
|
+
const promise = new Promise((resolve, reject) => {
|
|
330
332
|
parser(uri, options, (error, parsed) => {
|
|
331
333
|
if (error) {
|
|
332
334
|
if (_this.listeners('error').length > 0) {
|
|
@@ -335,7 +337,8 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
335
337
|
return reject(error);
|
|
336
338
|
}
|
|
337
339
|
|
|
338
|
-
|
|
340
|
+
dbName = dbName || parsed.dbName;
|
|
341
|
+
this.name = dbName;
|
|
339
342
|
this.host = parsed.servers[0].host || parsed.servers[0].domain_socket;
|
|
340
343
|
this.port = parsed.servers[0].port || 27017;
|
|
341
344
|
if (parsed.auth) {
|
|
@@ -353,7 +356,7 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
353
356
|
}
|
|
354
357
|
return reject(error);
|
|
355
358
|
}
|
|
356
|
-
|
|
359
|
+
const db = client.db(dbName);
|
|
357
360
|
_this.db = db;
|
|
358
361
|
_this.client = client;
|
|
359
362
|
|
|
@@ -394,7 +397,7 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
394
397
|
delete _this.catch;
|
|
395
398
|
_this.readyState = STATES.connected;
|
|
396
399
|
|
|
397
|
-
for (
|
|
400
|
+
for (let i in _this.collections) {
|
|
398
401
|
if (utils.object.hasOwnProperty(_this.collections, i)) {
|
|
399
402
|
_this.collections[i].onOpen();
|
|
400
403
|
}
|
package/lib/document.js
CHANGED
|
@@ -16,6 +16,7 @@ var VirtualType = require('./virtualtype');
|
|
|
16
16
|
var utils = require('./utils');
|
|
17
17
|
var clone = utils.clone;
|
|
18
18
|
var isDefiningProjection = require('./services/projection/isDefiningProjection');
|
|
19
|
+
var isExclusive = require('./services/projection/isExclusive');
|
|
19
20
|
var isMongooseObject = utils.isMongooseObject;
|
|
20
21
|
var inspect = require('util').inspect;
|
|
21
22
|
var internalToObjectOptions = require('./options').internalToObjectOptions;
|
|
@@ -71,7 +72,20 @@ function Document(obj, fields, skipId, options) {
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
this.$__.emitter.setMaxListeners(0);
|
|
74
|
-
|
|
75
|
+
|
|
76
|
+
let exclude = null;
|
|
77
|
+
|
|
78
|
+
// determine if this doc is a result of a query with
|
|
79
|
+
// excluded fields
|
|
80
|
+
if (fields && utils.getFunctionName(fields.constructor) === 'Object') {
|
|
81
|
+
exclude = isExclusive(fields);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let hasIncludedChildren = exclude === false && fields ?
|
|
85
|
+
$__hasIncludedChildren(fields) :
|
|
86
|
+
{};
|
|
87
|
+
|
|
88
|
+
this.$__buildDoc(obj, fields, skipId, exclude, hasIncludedChildren);
|
|
75
89
|
|
|
76
90
|
if (obj) {
|
|
77
91
|
if (obj instanceof Document) {
|
|
@@ -85,6 +99,8 @@ function Document(obj, fields, skipId, options) {
|
|
|
85
99
|
}
|
|
86
100
|
}
|
|
87
101
|
|
|
102
|
+
$__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren);
|
|
103
|
+
|
|
88
104
|
this.$__._id = this._id;
|
|
89
105
|
|
|
90
106
|
if (!schema.options.strict && obj) {
|
|
@@ -163,91 +179,52 @@ Document.prototype.id;
|
|
|
163
179
|
|
|
164
180
|
Document.prototype.errors;
|
|
165
181
|
|
|
166
|
-
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* @param {Object} obj
|
|
170
|
-
* @param {Object} [fields]
|
|
171
|
-
* @param {Boolean} [skipId]
|
|
172
|
-
* @return {Object}
|
|
173
|
-
* @api private
|
|
174
|
-
* @method $__buildDoc
|
|
175
|
-
* @memberOf Document
|
|
182
|
+
/*!
|
|
183
|
+
* ignore
|
|
176
184
|
*/
|
|
177
185
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
var keys;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (fields && utils.getFunctionName(fields.constructor) === 'Object') {
|
|
189
|
-
keys = Object.keys(fields);
|
|
190
|
-
ki = keys.length;
|
|
191
|
-
|
|
192
|
-
if (ki === 1 && keys[0] === '_id') {
|
|
193
|
-
exclude = !!fields[keys[ki]];
|
|
194
|
-
} else {
|
|
195
|
-
while (ki--) {
|
|
196
|
-
// Does this projection explicitly define inclusion/exclusion?
|
|
197
|
-
// Explicitly avoid `$meta` and `$slice`
|
|
198
|
-
if (keys[ki] !== '_id' && isDefiningProjection(fields[keys[ki]])) {
|
|
199
|
-
exclude = !fields[keys[ki]];
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
186
|
+
function $__hasIncludedChildren(fields) {
|
|
187
|
+
let hasIncludedChildren = {};
|
|
188
|
+
let keys = Object.keys(fields);
|
|
189
|
+
for (var j = 0; j < keys.length; ++j) {
|
|
190
|
+
let parts = keys[j].split('.');
|
|
191
|
+
let c = [];
|
|
192
|
+
for (var k = 0; k < parts.length; ++k) {
|
|
193
|
+
c.push(parts[k]);
|
|
194
|
+
hasIncludedChildren[c.join('.')] = 1;
|
|
203
195
|
}
|
|
204
196
|
}
|
|
205
197
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
var ii = 0;
|
|
198
|
+
return hasIncludedChildren;
|
|
199
|
+
}
|
|
209
200
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
for (var j = 0; j < keys.length; ++j) {
|
|
214
|
-
var parts = keys[j].split('.');
|
|
215
|
-
var c = [];
|
|
216
|
-
for (var k = 0; k < parts.length; ++k) {
|
|
217
|
-
c.push(parts[k]);
|
|
218
|
-
hasIncludedChildren[c.join('.')] = 1;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
201
|
+
/*!
|
|
202
|
+
* ignore
|
|
203
|
+
*/
|
|
222
204
|
|
|
223
|
-
|
|
224
|
-
|
|
205
|
+
function $__applyDefaults(doc, fields, skipId, exclude, hasIncludedChildren) {
|
|
206
|
+
const paths = Object.keys(doc.schema.paths);
|
|
207
|
+
const plen = paths.length;
|
|
225
208
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (obj && '_id' in obj) {
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
209
|
+
for (let i = 0; i < plen; ++i) {
|
|
210
|
+
let def;
|
|
211
|
+
let curPath = '';
|
|
212
|
+
let p = paths[i];
|
|
234
213
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
var last = len - 1;
|
|
239
|
-
var curPath = '';
|
|
240
|
-
var doc_ = doc;
|
|
241
|
-
var i = 0;
|
|
242
|
-
var included = false;
|
|
214
|
+
if (p === '_id' && skipId) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
243
217
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
218
|
+
let type = doc.schema.paths[p];
|
|
219
|
+
let path = p.split('.');
|
|
220
|
+
let len = path.length;
|
|
221
|
+
let included = false;
|
|
222
|
+
let doc_ = doc._doc;
|
|
247
223
|
|
|
224
|
+
for (let j = 0; j < len; ++j) {
|
|
225
|
+
let piece = path[j];
|
|
248
226
|
curPath += (!curPath.length ? '' : '.') + piece;
|
|
249
227
|
|
|
250
|
-
// support excluding intermediary levels
|
|
251
228
|
if (exclude === true) {
|
|
252
229
|
if (curPath in fields) {
|
|
253
230
|
break;
|
|
@@ -260,7 +237,11 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) {
|
|
|
260
237
|
}
|
|
261
238
|
}
|
|
262
239
|
|
|
263
|
-
if (
|
|
240
|
+
if (j === len - 1) {
|
|
241
|
+
if (doc_[piece] !== void 0) {
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
|
|
264
245
|
if (fields && exclude !== null) {
|
|
265
246
|
if (exclude === true) {
|
|
266
247
|
// apply defaults to all non-excluded fields
|
|
@@ -268,33 +249,95 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) {
|
|
|
268
249
|
continue;
|
|
269
250
|
}
|
|
270
251
|
|
|
271
|
-
def = type.getDefault(
|
|
252
|
+
def = type.getDefault(doc, false);
|
|
272
253
|
if (typeof def !== 'undefined') {
|
|
273
254
|
doc_[piece] = def;
|
|
274
|
-
|
|
255
|
+
doc.$__.activePaths.default(p);
|
|
275
256
|
}
|
|
276
257
|
} else if (included) {
|
|
277
258
|
// selected field
|
|
278
|
-
def = type.getDefault(
|
|
259
|
+
def = type.getDefault(doc, false);
|
|
279
260
|
if (typeof def !== 'undefined') {
|
|
280
261
|
doc_[piece] = def;
|
|
281
|
-
|
|
262
|
+
doc.$__.activePaths.default(p);
|
|
282
263
|
}
|
|
283
264
|
}
|
|
284
265
|
} else {
|
|
285
|
-
def = type.getDefault(
|
|
266
|
+
def = type.getDefault(doc, false);
|
|
286
267
|
if (typeof def !== 'undefined') {
|
|
287
268
|
doc_[piece] = def;
|
|
288
|
-
|
|
269
|
+
doc.$__.activePaths.default(p);
|
|
289
270
|
}
|
|
290
271
|
}
|
|
291
272
|
} else {
|
|
273
|
+
doc_ = doc_[piece];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Builds the default doc structure
|
|
281
|
+
*
|
|
282
|
+
* @param {Object} obj
|
|
283
|
+
* @param {Object} [fields]
|
|
284
|
+
* @param {Boolean} [skipId]
|
|
285
|
+
* @api private
|
|
286
|
+
* @method $__buildDoc
|
|
287
|
+
* @memberOf Document
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
Document.prototype.$__buildDoc = function(obj, fields, skipId, exclude, hasIncludedChildren) {
|
|
291
|
+
const doc = {};
|
|
292
|
+
|
|
293
|
+
const paths = Object.keys(this.schema.paths);
|
|
294
|
+
const plen = paths.length;
|
|
295
|
+
let ii = 0;
|
|
296
|
+
|
|
297
|
+
for (; ii < plen; ++ii) {
|
|
298
|
+
var p = paths[ii];
|
|
299
|
+
|
|
300
|
+
if (p === '_id') {
|
|
301
|
+
if (skipId) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (obj && '_id' in obj) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const path = p.split('.');
|
|
310
|
+
const len = path.length;
|
|
311
|
+
const last = len - 1;
|
|
312
|
+
let curPath = '';
|
|
313
|
+
let doc_ = doc;
|
|
314
|
+
let included = false;
|
|
315
|
+
|
|
316
|
+
for (let i = 0; i < len; ++i) {
|
|
317
|
+
const piece = path[i];
|
|
318
|
+
|
|
319
|
+
curPath += (!curPath.length ? '' : '.') + piece;
|
|
320
|
+
|
|
321
|
+
// support excluding intermediary levels
|
|
322
|
+
if (exclude === true) {
|
|
323
|
+
if (curPath in fields) {
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
} else if (exclude === false && fields && !included) {
|
|
327
|
+
if (curPath in fields) {
|
|
328
|
+
included = true;
|
|
329
|
+
} else if (!hasIncludedChildren[curPath]) {
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (i < last) {
|
|
292
335
|
doc_ = doc_[piece] || (doc_[piece] = {});
|
|
293
336
|
}
|
|
294
337
|
}
|
|
295
338
|
}
|
|
296
339
|
|
|
297
|
-
|
|
340
|
+
this._doc = doc;
|
|
298
341
|
};
|
|
299
342
|
|
|
300
343
|
/*!
|
|
@@ -1103,12 +1146,12 @@ Document.prototype.modifiedPaths = function() {
|
|
|
1103
1146
|
* @api public
|
|
1104
1147
|
*/
|
|
1105
1148
|
|
|
1106
|
-
Document.prototype.isModified = function(paths) {
|
|
1149
|
+
Document.prototype.isModified = function(paths, modifiedPaths) {
|
|
1107
1150
|
if (paths) {
|
|
1108
1151
|
if (!Array.isArray(paths)) {
|
|
1109
1152
|
paths = paths.split(' ');
|
|
1110
1153
|
}
|
|
1111
|
-
var modified = this.modifiedPaths();
|
|
1154
|
+
var modified = modifiedPaths || this.modifiedPaths();
|
|
1112
1155
|
var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
|
|
1113
1156
|
var isModifiedChild = paths.some(function(path) {
|
|
1114
1157
|
return !!~modified.indexOf(path);
|
|
@@ -1394,9 +1437,10 @@ function _getPathsToValidate(doc) {
|
|
|
1394
1437
|
var subdocs = doc.$__getAllSubdocs();
|
|
1395
1438
|
var subdoc;
|
|
1396
1439
|
len = subdocs.length;
|
|
1440
|
+
var modifiedPaths = doc.modifiedPaths();
|
|
1397
1441
|
for (i = 0; i < len; ++i) {
|
|
1398
1442
|
subdoc = subdocs[i];
|
|
1399
|
-
if (doc.isModified(subdoc.$basePath) &&
|
|
1443
|
+
if (doc.isModified(subdoc.$basePath, modifiedPaths) &&
|
|
1400
1444
|
!doc.isDirectModified(subdoc.$basePath)) {
|
|
1401
1445
|
// Remove child paths for now, because we'll be validating the whole
|
|
1402
1446
|
// subdoc
|
package/lib/index.js
CHANGED
|
@@ -285,6 +285,7 @@ Mongoose.prototype.pluralize = function(fn) {
|
|
|
285
285
|
* @param {Schema} [schema]
|
|
286
286
|
* @param {String} [collection] name (optional, inferred from model name)
|
|
287
287
|
* @param {Boolean} [skipInit] whether to skip initialization (defaults to false)
|
|
288
|
+
* @return {Model}
|
|
288
289
|
* @api public
|
|
289
290
|
*/
|
|
290
291
|
|
package/lib/model.js
CHANGED
|
@@ -770,7 +770,7 @@ Model.prototype.remove = function remove(options, fn) {
|
|
|
770
770
|
|
|
771
771
|
Model.prototype.$__remove = function $__remove(options, cb) {
|
|
772
772
|
if (this.$__.isDeleted) {
|
|
773
|
-
return
|
|
773
|
+
return utils.immediate(() => cb(null, this));
|
|
774
774
|
}
|
|
775
775
|
|
|
776
776
|
var where = this.$__where();
|
|
@@ -1030,7 +1030,7 @@ function _ensureIndexes(model, options, callback) {
|
|
|
1030
1030
|
};
|
|
1031
1031
|
|
|
1032
1032
|
if (!indexes.length) {
|
|
1033
|
-
|
|
1033
|
+
utils.immediate(function() {
|
|
1034
1034
|
done();
|
|
1035
1035
|
});
|
|
1036
1036
|
return;
|
|
@@ -1071,7 +1071,7 @@ function _ensureIndexes(model, options, callback) {
|
|
|
1071
1071
|
}));
|
|
1072
1072
|
};
|
|
1073
1073
|
|
|
1074
|
-
|
|
1074
|
+
utils.immediate(function() {
|
|
1075
1075
|
// If buffering is off, do this manually.
|
|
1076
1076
|
if (options._automatic && !model.collection.collection) {
|
|
1077
1077
|
model.collection.addQueue(create, []);
|
|
@@ -2751,13 +2751,13 @@ Model.mapReduce = function mapReduce(o, callback) {
|
|
|
2751
2751
|
* ####Example:
|
|
2752
2752
|
*
|
|
2753
2753
|
* // Find the max balance of all accounts
|
|
2754
|
-
* Users.aggregate(
|
|
2754
|
+
* Users.aggregate([
|
|
2755
2755
|
* { $group: { _id: null, maxBalance: { $max: '$balance' }}},
|
|
2756
|
-
* { $project: { _id: 0, maxBalance: 1 }}
|
|
2757
|
-
*
|
|
2758
|
-
*
|
|
2759
|
-
*
|
|
2760
|
-
*
|
|
2756
|
+
* { $project: { _id: 0, maxBalance: 1 }}
|
|
2757
|
+
* ]).
|
|
2758
|
+
* then(function (res) {
|
|
2759
|
+
* console.log(res); // [ { maxBalance: 98000 } ]
|
|
2760
|
+
* });
|
|
2761
2761
|
*
|
|
2762
2762
|
* // Or use the aggregation pipeline builder.
|
|
2763
2763
|
* Users.aggregate()
|
|
@@ -2766,7 +2766,7 @@ Model.mapReduce = function mapReduce(o, callback) {
|
|
|
2766
2766
|
* .exec(function (err, res) {
|
|
2767
2767
|
* if (err) return handleError(err);
|
|
2768
2768
|
* console.log(res); // [ { maxBalance: 98 } ]
|
|
2769
|
-
*
|
|
2769
|
+
* });
|
|
2770
2770
|
*
|
|
2771
2771
|
* ####NOTE:
|
|
2772
2772
|
*
|
|
@@ -3036,7 +3036,7 @@ function populate(model, docs, options, callback) {
|
|
|
3036
3036
|
|
|
3037
3037
|
modelsMap = getModelsMapForPopulate(model, docs, options);
|
|
3038
3038
|
if (modelsMap instanceof Error) {
|
|
3039
|
-
return
|
|
3039
|
+
return utils.immediate(function() {
|
|
3040
3040
|
callback(modelsMap);
|
|
3041
3041
|
});
|
|
3042
3042
|
}
|
package/lib/schema/array.js
CHANGED
|
@@ -17,6 +17,7 @@ var Types = {
|
|
|
17
17
|
};
|
|
18
18
|
var Mixed = require('./mixed');
|
|
19
19
|
var cast = require('../cast');
|
|
20
|
+
var get = require('lodash.get');
|
|
20
21
|
var util = require('util');
|
|
21
22
|
var utils = require('../utils');
|
|
22
23
|
var castToNumber = require('./operators/helpers').castToNumber;
|
|
@@ -119,6 +120,23 @@ SchemaArray.schemaName = 'Array';
|
|
|
119
120
|
SchemaArray.prototype = Object.create(SchemaType.prototype);
|
|
120
121
|
SchemaArray.prototype.constructor = SchemaArray;
|
|
121
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Adds an enum validator if this is an array of strings. Equivalent to
|
|
125
|
+
* `SchemaString.prototype.enum()`
|
|
126
|
+
*
|
|
127
|
+
* @param {String|Object} [args...] enumeration values
|
|
128
|
+
* @return {SchemaType} this
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
SchemaArray.prototype.enum = function() {
|
|
132
|
+
const instance = get(this, 'caster.instance');
|
|
133
|
+
if (instance !== 'String') {
|
|
134
|
+
throw new Error('`enum` can only be set on an array of strings, not ' + instance);
|
|
135
|
+
}
|
|
136
|
+
this.caster.enum.apply(this.caster, arguments);
|
|
137
|
+
return this;
|
|
138
|
+
};
|
|
139
|
+
|
|
122
140
|
/**
|
|
123
141
|
* Check if the given value satisfies a required validator. The given value
|
|
124
142
|
* must be not null nor undefined, and have a positive length.
|
package/lib/schema/objectid.js
CHANGED
|
@@ -20,7 +20,7 @@ var SchemaType = require('../schematype'),
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
function ObjectId(key, options) {
|
|
23
|
-
var isKeyHexStr = typeof key === 'string' && key.length === 24 && /^a-f0-9
|
|
23
|
+
var isKeyHexStr = typeof key === 'string' && key.length === 24 && /^[a-f0-9]+$/i.test(key);
|
|
24
24
|
var suppressWarning = options && options.suppressWarning;
|
|
25
25
|
if ((isKeyHexStr || typeof key === 'undefined') && !suppressWarning) {
|
|
26
26
|
console.warn('mongoose: To create a new ObjectId please try ' +
|
|
@@ -209,15 +209,16 @@ function defaultId() {
|
|
|
209
209
|
function resetId(v) {
|
|
210
210
|
Document || (Document = require('./../document'));
|
|
211
211
|
|
|
212
|
-
if (v === void 0) {
|
|
213
|
-
var _v = new oid;
|
|
214
|
-
this.$__._id = _v;
|
|
215
|
-
return _v;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
212
|
if (this instanceof Document) {
|
|
213
|
+
if (v === void 0) {
|
|
214
|
+
var _v = new oid;
|
|
215
|
+
this.$__._id = _v;
|
|
216
|
+
return _v;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
219
|
this.$__._id = v;
|
|
220
220
|
}
|
|
221
|
+
|
|
221
222
|
return v;
|
|
222
223
|
}
|
|
223
224
|
|