mongoose 5.0.18 → 5.1.0
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 +16 -0
- package/lib/document.js +68 -12
- package/lib/drivers/browser/objectid.js +12 -0
- package/lib/drivers/node-mongodb-native/collection.js +10 -3
- package/lib/error/version.js +3 -2
- package/lib/index.js +10 -5
- package/lib/internal.js +1 -0
- package/lib/model.js +239 -36
- package/lib/plugins/saveSubdocs.js +1 -1
- package/lib/query.js +191 -97
- package/lib/queryhelpers.js +25 -23
- package/lib/schema/array.js +6 -3
- 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 +47 -9
- package/lib/schematype.js +19 -1
- package/lib/services/model/applyMethods.js +14 -4
- package/lib/services/query/completeMany.js +47 -0
- package/lib/types/embedded.js +33 -1
- package/lib/types/index.js +2 -0
- package/lib/types/map.js +144 -0
- package/lib/types/objectid.js +12 -0
- package/lib/types/subdocument.js +30 -1
- package/lib/utils.js +5 -3
- package/package.json +1 -1
package/.travis.yml
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
language: node_js
|
|
2
2
|
sudo: false
|
|
3
3
|
node_js:
|
|
4
|
+
- "10"
|
|
4
5
|
- "9"
|
|
5
6
|
- "8"
|
|
6
7
|
- "7"
|
|
@@ -8,11 +9,11 @@ node_js:
|
|
|
8
9
|
- "5"
|
|
9
10
|
- "4"
|
|
10
11
|
before_script:
|
|
11
|
-
- wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.
|
|
12
|
-
- tar -zxvf mongodb-linux-x86_64-3.
|
|
12
|
+
- wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.4.tgz
|
|
13
|
+
- tar -zxvf mongodb-linux-x86_64-3.6.4.tgz
|
|
13
14
|
- mkdir -p ./data/db/27017
|
|
14
15
|
- mkdir -p ./data/db/27000
|
|
15
|
-
- ./mongodb-linux-x86_64-3.
|
|
16
|
+
- ./mongodb-linux-x86_64-3.6.4/bin/mongod --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017
|
|
16
17
|
script:
|
|
17
18
|
- npm test
|
|
18
19
|
- npm run lint
|
package/History.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
5.1.0 / 2018-05-10
|
|
2
|
+
==================
|
|
3
|
+
* feat(ObjectId): add `_id` getter so you can get a usable id whether or not the path is populated #6415 #6115
|
|
4
|
+
* feat(model): add Model.startSession() #6362
|
|
5
|
+
* feat(document): add doc.$session() and set session on doc after query #6362
|
|
6
|
+
* feat: add Map type that supports arbitrary keys #6287 #681
|
|
7
|
+
* feat: add `cloneSchemas` option to mongoose global to opt in to always cloning schemas before use #6274
|
|
8
|
+
* feat(model): add `findOneAndDelete()` and `findByIdAndDelete()` #6164
|
|
9
|
+
* feat(document): support `$ignore()` on single nested and array subdocs #6152
|
|
10
|
+
* feat(document): add warning about calling `save()` on subdocs #6152
|
|
11
|
+
* fix(model): make `save()` use `updateOne()` instead of `update()` #6031
|
|
12
|
+
* feat(error): add version number to VersionError #5966
|
|
13
|
+
* fix(query): allow `[]` as a value for `$in` when casting #5913
|
|
14
|
+
* fix(document): avoid running validators on single nested paths if only a child path is modified #5885
|
|
15
|
+
* feat(schema): print warning if method conflicts with mongoose internals #5860
|
|
16
|
+
|
|
1
17
|
5.0.18 / 2018-05-09
|
|
2
18
|
===================
|
|
3
19
|
* fix(update): stop clobbering $in when casting update #6441 #6339 [lineus](https://github.com/lineus)
|
package/lib/document.js
CHANGED
|
@@ -326,7 +326,10 @@ function $__applyDefaults(doc, fields, skipId, exclude, hasIncludedChildren, isB
|
|
|
326
326
|
Document.prototype.$__buildDoc = function(obj, fields, skipId, exclude, hasIncludedChildren) {
|
|
327
327
|
const doc = {};
|
|
328
328
|
|
|
329
|
-
const paths = Object.keys(this.schema.paths)
|
|
329
|
+
const paths = Object.keys(this.schema.paths).
|
|
330
|
+
// Don't build up any paths that are underneath a map, we don't know
|
|
331
|
+
// what the keys will be
|
|
332
|
+
filter(p => !p.includes('$*'));
|
|
330
333
|
const plen = paths.length;
|
|
331
334
|
let ii = 0;
|
|
332
335
|
|
|
@@ -541,6 +544,26 @@ Document.prototype.update = function update() {
|
|
|
541
544
|
return this.constructor.update.apply(this.constructor, args);
|
|
542
545
|
};
|
|
543
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Getter/setter around the session associated with this document. Used to
|
|
549
|
+
* automatically set `session` if you `save()` a doc that you got from a
|
|
550
|
+
* query with an associated session.
|
|
551
|
+
*
|
|
552
|
+
* @param {ClientSession} [session] overwrite the current session
|
|
553
|
+
* @return {ClientSession}
|
|
554
|
+
* @method $session
|
|
555
|
+
* @api public
|
|
556
|
+
* @memberOf Document
|
|
557
|
+
*/
|
|
558
|
+
|
|
559
|
+
Document.prototype.$session = function $session(session) {
|
|
560
|
+
if (arguments.length === 0) {
|
|
561
|
+
return this.$__.session;
|
|
562
|
+
}
|
|
563
|
+
this.$__.session = session;
|
|
564
|
+
return session;
|
|
565
|
+
};
|
|
566
|
+
|
|
544
567
|
/**
|
|
545
568
|
* Alias for `set()`, used internally to avoid conflicts
|
|
546
569
|
*
|
|
@@ -978,7 +1001,11 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche
|
|
|
978
1001
|
cur += (cur ? '.' + parts[i] : parts[i]);
|
|
979
1002
|
|
|
980
1003
|
if (last) {
|
|
981
|
-
obj
|
|
1004
|
+
if (obj instanceof Map) {
|
|
1005
|
+
obj.set(parts[i], val);
|
|
1006
|
+
} else {
|
|
1007
|
+
obj[parts[i]] = val;
|
|
1008
|
+
}
|
|
982
1009
|
} else {
|
|
983
1010
|
if (obj[parts[i]] && utils.getFunctionName(obj[parts[i]].constructor) === 'Object') {
|
|
984
1011
|
obj = obj[parts[i]];
|
|
@@ -1055,9 +1082,13 @@ Document.prototype.get = function(path, type, options) {
|
|
|
1055
1082
|
}
|
|
1056
1083
|
|
|
1057
1084
|
for (var i = 0, l = pieces.length; i < l; i++) {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1085
|
+
if (obj == null) {
|
|
1086
|
+
obj = void 0;
|
|
1087
|
+
} else if (obj instanceof Map) {
|
|
1088
|
+
obj = obj.get(pieces[i]);
|
|
1089
|
+
} else {
|
|
1090
|
+
obj = obj[pieces[i]];
|
|
1091
|
+
}
|
|
1061
1092
|
}
|
|
1062
1093
|
|
|
1063
1094
|
if (adhoc) {
|
|
@@ -1485,6 +1516,7 @@ Document.prototype.validate = function(options, callback) {
|
|
|
1485
1516
|
function _getPathsToValidate(doc) {
|
|
1486
1517
|
var i;
|
|
1487
1518
|
var len;
|
|
1519
|
+
var skipSchemaValidators = {};
|
|
1488
1520
|
|
|
1489
1521
|
// only validate required fields when necessary
|
|
1490
1522
|
var paths = Object.keys(doc.$__.activePaths.states.require).filter(function(path) {
|
|
@@ -1517,6 +1549,7 @@ function _getPathsToValidate(doc) {
|
|
|
1517
1549
|
return p != null && p.indexOf(subdoc.$basePath + '.') !== 0;
|
|
1518
1550
|
});
|
|
1519
1551
|
paths.push(subdoc.$basePath);
|
|
1552
|
+
skipSchemaValidators[subdoc.$basePath] = true;
|
|
1520
1553
|
}
|
|
1521
1554
|
}
|
|
1522
1555
|
}
|
|
@@ -1563,7 +1596,24 @@ function _getPathsToValidate(doc) {
|
|
|
1563
1596
|
}
|
|
1564
1597
|
}
|
|
1565
1598
|
|
|
1566
|
-
|
|
1599
|
+
len = paths.length;
|
|
1600
|
+
for (i = 0; i < len; ++i) {
|
|
1601
|
+
const path = paths[i];
|
|
1602
|
+
const _pathType = doc.schema.path(path);
|
|
1603
|
+
if (!_pathType || !_pathType.$isSchemaMap) {
|
|
1604
|
+
continue;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
const val = doc.getValue(path);
|
|
1608
|
+
if (val == null) {
|
|
1609
|
+
continue;
|
|
1610
|
+
}
|
|
1611
|
+
for (let key of val.keys()) {
|
|
1612
|
+
paths.push(path + '.' + key);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
return [paths, skipSchemaValidators];
|
|
1567
1617
|
}
|
|
1568
1618
|
|
|
1569
1619
|
/*!
|
|
@@ -1590,7 +1640,9 @@ Document.prototype.$__validate = function(callback) {
|
|
|
1590
1640
|
};
|
|
1591
1641
|
|
|
1592
1642
|
// only validate required fields when necessary
|
|
1593
|
-
const
|
|
1643
|
+
const pathDetails = _getPathsToValidate(this);
|
|
1644
|
+
const paths = pathDetails[0];
|
|
1645
|
+
const skipSchemaValidators = pathDetails[1];
|
|
1594
1646
|
|
|
1595
1647
|
if (paths.length === 0) {
|
|
1596
1648
|
return process.nextTick(function() {
|
|
@@ -1627,6 +1679,7 @@ Document.prototype.$__validate = function(callback) {
|
|
|
1627
1679
|
|
|
1628
1680
|
process.nextTick(function() {
|
|
1629
1681
|
const p = _this.schema.path(path);
|
|
1682
|
+
|
|
1630
1683
|
if (!p) {
|
|
1631
1684
|
return --total || complete();
|
|
1632
1685
|
}
|
|
@@ -1647,7 +1700,7 @@ Document.prototype.$__validate = function(callback) {
|
|
|
1647
1700
|
_this.invalidate(path, err, undefined, true);
|
|
1648
1701
|
}
|
|
1649
1702
|
--total || complete();
|
|
1650
|
-
}, scope);
|
|
1703
|
+
}, scope, { skipSchemaValidators: skipSchemaValidators[path] });
|
|
1651
1704
|
});
|
|
1652
1705
|
};
|
|
1653
1706
|
|
|
@@ -1679,14 +1732,16 @@ Document.prototype.$__validate = function(callback) {
|
|
|
1679
1732
|
*/
|
|
1680
1733
|
|
|
1681
1734
|
Document.prototype.validateSync = function(pathsToValidate) {
|
|
1682
|
-
|
|
1735
|
+
const _this = this;
|
|
1683
1736
|
|
|
1684
1737
|
if (typeof pathsToValidate === 'string') {
|
|
1685
1738
|
pathsToValidate = pathsToValidate.split(' ');
|
|
1686
1739
|
}
|
|
1687
1740
|
|
|
1688
1741
|
// only validate required fields when necessary
|
|
1689
|
-
|
|
1742
|
+
const pathDetails = _getPathsToValidate(this);
|
|
1743
|
+
let paths = pathDetails[0];
|
|
1744
|
+
const skipSchemaValidators = pathDetails[1];
|
|
1690
1745
|
|
|
1691
1746
|
if (pathsToValidate && pathsToValidate.length) {
|
|
1692
1747
|
var tmp = [];
|
|
@@ -1716,7 +1771,9 @@ Document.prototype.validateSync = function(pathsToValidate) {
|
|
|
1716
1771
|
}
|
|
1717
1772
|
|
|
1718
1773
|
var val = _this.getValue(path);
|
|
1719
|
-
var err = p.doValidateSync(val, _this
|
|
1774
|
+
var err = p.doValidateSync(val, _this, {
|
|
1775
|
+
skipSchemaValidators: skipSchemaValidators[path]
|
|
1776
|
+
});
|
|
1720
1777
|
if (err) {
|
|
1721
1778
|
_this.invalidate(path, err, undefined, true);
|
|
1722
1779
|
}
|
|
@@ -2691,7 +2748,6 @@ Document.prototype.execPopulate = function() {
|
|
|
2691
2748
|
|
|
2692
2749
|
Document.prototype.populated = function(path, val, options) {
|
|
2693
2750
|
// val and options are internal
|
|
2694
|
-
|
|
2695
2751
|
if (val === null || val === void 0) {
|
|
2696
2752
|
if (!this.$__.populated) {
|
|
2697
2753
|
return undefined;
|
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
|
|
8
8
|
var ObjectId = require('bson').ObjectID;
|
|
9
9
|
|
|
10
|
+
/*!
|
|
11
|
+
* Getter for convenience with populate, see gh-6115
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
Object.defineProperty(ObjectId.prototype, '_id', {
|
|
15
|
+
enumerable: false,
|
|
16
|
+
configurable: true,
|
|
17
|
+
get: function() {
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
10
22
|
/*!
|
|
11
23
|
* ignore
|
|
12
24
|
*/
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
1
3
|
/*!
|
|
2
4
|
* Module dependencies.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
const MongooseCollection = require('../../collection');
|
|
8
|
+
const Collection = require('mongodb').Collection;
|
|
9
|
+
const get = require('lodash.get');
|
|
10
|
+
const utils = require('../../utils');
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation.
|
|
@@ -248,6 +251,10 @@ function format(obj, sub) {
|
|
|
248
251
|
formatObjectId(x, key);
|
|
249
252
|
} else if (x[key].constructor.name === 'Date') {
|
|
250
253
|
formatDate(x, key);
|
|
254
|
+
} else if (x[key].constructor.name === 'ClientSession') {
|
|
255
|
+
representation = 'ClientSession("' +
|
|
256
|
+
get(x[key], 'id.id.buffer', '').toString('hex') + '")';
|
|
257
|
+
x[key] = {inspect: function() { return representation; }};
|
|
251
258
|
} else if (Array.isArray(x[key])) {
|
|
252
259
|
x[key] = x[key].map(map);
|
|
253
260
|
}
|
package/lib/error/version.js
CHANGED
|
@@ -13,10 +13,11 @@ var MongooseError = require('./');
|
|
|
13
13
|
* @api private
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
function VersionError(doc) {
|
|
16
|
+
function VersionError(doc, currentVersion) {
|
|
17
17
|
MongooseError.call(this, 'No matching document found for id "' + doc._id +
|
|
18
|
-
'"');
|
|
18
|
+
'" version ' + currentVersion);
|
|
19
19
|
this.name = 'VersionError';
|
|
20
|
+
this.version = currentVersion;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/*!
|
package/lib/index.js
CHANGED
|
@@ -80,6 +80,7 @@ Mongoose.prototype.STATES = STATES;
|
|
|
80
80
|
* - 'debug': prints the operations mongoose sends to MongoDB to the console
|
|
81
81
|
* - 'bufferCommands': enable/disable mongoose's buffering mechanism for all connections and models
|
|
82
82
|
* - 'useFindAndModify': true by default. Set to `false` to make `findOneAndUpdate()` and `findOneAndRemove()` use native `findOneAndUpdate()` rather than `findAndModify()`.
|
|
83
|
+
* - 'cloneSchemas': false by default. Set to `true` to `clone()` all schemas before compiling into a model.
|
|
83
84
|
*
|
|
84
85
|
* @param {String} key
|
|
85
86
|
* @param {String|Function|Boolean} value
|
|
@@ -291,7 +292,7 @@ Mongoose.prototype.pluralize = function(fn) {
|
|
|
291
292
|
*/
|
|
292
293
|
|
|
293
294
|
Mongoose.prototype.model = function(name, schema, collection, skipInit) {
|
|
294
|
-
|
|
295
|
+
let model;
|
|
295
296
|
if (typeof name === 'function') {
|
|
296
297
|
model = name;
|
|
297
298
|
name = model.name;
|
|
@@ -319,7 +320,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
|
|
|
319
320
|
}
|
|
320
321
|
|
|
321
322
|
// handle internal options from connection.model()
|
|
322
|
-
|
|
323
|
+
let options;
|
|
323
324
|
if (skipInit && utils.isObject(skipInit)) {
|
|
324
325
|
options = skipInit;
|
|
325
326
|
skipInit = true;
|
|
@@ -337,16 +338,20 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
|
|
|
337
338
|
}
|
|
338
339
|
}
|
|
339
340
|
|
|
341
|
+
const originalSchema = schema;
|
|
340
342
|
if (schema) {
|
|
343
|
+
if (this.get('cloneSchemas')) {
|
|
344
|
+
schema = schema.clone();
|
|
345
|
+
}
|
|
341
346
|
this._applyPlugins(schema);
|
|
342
347
|
}
|
|
343
348
|
|
|
344
|
-
|
|
349
|
+
let sub;
|
|
345
350
|
|
|
346
351
|
// connection.model() may be passing a different schema for
|
|
347
352
|
// an existing model name. in this case don't read from cache.
|
|
348
353
|
if (this.models[name] && options.cache !== false) {
|
|
349
|
-
if (
|
|
354
|
+
if (originalSchema && originalSchema.instanceOfSchema && originalSchema !== this.models[name].schema) {
|
|
350
355
|
throw new mongoose.Error.OverwriteModelError(name);
|
|
351
356
|
}
|
|
352
357
|
|
|
@@ -380,7 +385,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
|
|
|
380
385
|
utils.toCollectionName(name, this.pluralize());
|
|
381
386
|
}
|
|
382
387
|
|
|
383
|
-
|
|
388
|
+
const connection = options.connection || this.connection;
|
|
384
389
|
model = this.Model.compile(model || name, schema, collection, connection, this);
|
|
385
390
|
|
|
386
391
|
if (!skipInit) {
|