mongoose 6.2.8 → 6.2.11

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.
Files changed (61) hide show
  1. package/.eslintrc.json +35 -26
  2. package/CHANGELOG.md +28 -0
  3. package/dist/browser.umd.js +38 -27
  4. package/lib/aggregate.js +57 -66
  5. package/lib/browser.js +4 -4
  6. package/lib/connection.js +21 -21
  7. package/lib/cursor/AggregationCursor.js +2 -2
  8. package/lib/cursor/QueryCursor.js +3 -3
  9. package/lib/document.js +65 -49
  10. package/lib/error/index.js +2 -2
  11. package/lib/helpers/indexes/applySchemaCollation.js +13 -0
  12. package/lib/helpers/indexes/isTextIndex.js +16 -0
  13. package/lib/helpers/populate/markArraySubdocsPopulated.js +1 -1
  14. package/lib/helpers/projection/hasIncludedChildren.js +1 -1
  15. package/lib/helpers/query/castUpdate.js +3 -1
  16. package/lib/helpers/update/applyTimestampsToChildren.js +2 -2
  17. package/lib/helpers/update/applyTimestampsToUpdate.js +0 -1
  18. package/lib/index.js +24 -26
  19. package/lib/model.js +144 -146
  20. package/lib/options/SchemaArrayOptions.js +2 -2
  21. package/lib/options/SchemaBufferOptions.js +1 -1
  22. package/lib/options/SchemaDateOptions.js +9 -2
  23. package/lib/options/SchemaDocumentArrayOptions.js +3 -3
  24. package/lib/options/SchemaMapOptions.js +2 -2
  25. package/lib/options/SchemaNumberOptions.js +3 -3
  26. package/lib/options/SchemaObjectIdOptions.js +2 -2
  27. package/lib/options/SchemaStringOptions.js +1 -1
  28. package/lib/options/SchemaSubdocumentOptions.js +2 -2
  29. package/lib/options/SchemaTypeOptions.js +3 -3
  30. package/lib/query.js +291 -248
  31. package/lib/schema/SubdocumentPath.js +4 -3
  32. package/lib/schema/array.js +2 -2
  33. package/lib/schema/boolean.js +4 -4
  34. package/lib/schema/buffer.js +3 -3
  35. package/lib/schema/date.js +7 -7
  36. package/lib/schema/decimal128.js +2 -2
  37. package/lib/schema/documentarray.js +3 -3
  38. package/lib/schema/mixed.js +2 -2
  39. package/lib/schema/number.js +6 -6
  40. package/lib/schema/objectid.js +4 -7
  41. package/lib/schema/string.js +38 -16
  42. package/lib/schema.js +30 -29
  43. package/lib/schematype.js +78 -69
  44. package/lib/types/ArraySubdocument.js +1 -1
  45. package/lib/types/DocumentArray/methods/index.js +2 -2
  46. package/lib/types/array/index.js +1 -1
  47. package/lib/types/array/methods/index.js +13 -13
  48. package/lib/types/buffer.js +1 -1
  49. package/lib/types/decimal128.js +1 -1
  50. package/lib/types/objectid.js +1 -1
  51. package/lib/types/subdocument.js +31 -2
  52. package/lib/virtualtype.js +3 -3
  53. package/package.json +18 -16
  54. package/tools/repl.js +8 -8
  55. package/tools/sharded.js +3 -3
  56. package/types/aggregate.d.ts +223 -0
  57. package/types/connection.d.ts +116 -116
  58. package/types/error.d.ts +2 -2
  59. package/types/index.d.ts +76 -213
  60. package/types/pipelinestage.d.ts +194 -194
  61. package/types/schemaoptions.d.ts +2 -2
@@ -112,7 +112,7 @@ QueryCursor.prototype._read = function() {
112
112
  * Registers a transform function which subsequently maps documents retrieved
113
113
  * via the streams interface or `.next()`
114
114
  *
115
- * ####Example
115
+ * #### Example
116
116
  *
117
117
  * // Map documents returned by `data` events
118
118
  * Thing.
@@ -211,7 +211,7 @@ QueryCursor.prototype.next = function(callback) {
211
211
  * will wait for the promise to resolve before iterating on to the next one.
212
212
  * Returns a promise that resolves when done.
213
213
  *
214
- * ####Example
214
+ * #### Example
215
215
  *
216
216
  * // Iterate over documents asynchronously
217
217
  * Thing.
@@ -298,7 +298,7 @@ QueryCursor.prototype._transformForAsyncIterator = function() {
298
298
  * You do not need to call this function explicitly, the JavaScript runtime
299
299
  * will call it for you.
300
300
  *
301
- * ####Example
301
+ * #### Example
302
302
  *
303
303
  * // Works without using `cursor()`
304
304
  * for await (const doc of Model.find([{ $sort: { name: 1 } }])) {
package/lib/document.js CHANGED
@@ -94,7 +94,7 @@ function Document(obj, fields, skipId, options) {
94
94
  this.$__ = new InternalCache();
95
95
  this.$isNew = 'isNew' in options ? options.isNew : true;
96
96
 
97
- if ('priorDoc' in options) {
97
+ if (options.priorDoc != null) {
98
98
  this.$__.priorDoc = options.priorDoc;
99
99
  }
100
100
 
@@ -119,7 +119,7 @@ function Document(obj, fields, skipId, options) {
119
119
  fields = undefined;
120
120
  } else {
121
121
  this.$__.strictMode = schema.options.strict;
122
- if (fields !== undefined) {
122
+ if (fields != null) {
123
123
  this.$__.selected = fields;
124
124
  }
125
125
  }
@@ -156,9 +156,9 @@ function Document(obj, fields, skipId, options) {
156
156
  if (obj) {
157
157
  // Skip set hooks
158
158
  if (this.$__original_set) {
159
- this.$__original_set(obj, undefined, true);
159
+ this.$__original_set(obj, undefined, true, options);
160
160
  } else {
161
- this.$set(obj, undefined, true);
161
+ this.$set(obj, undefined, true, options);
162
162
  }
163
163
 
164
164
  if (obj instanceof Document) {
@@ -177,8 +177,6 @@ function Document(obj, fields, skipId, options) {
177
177
  $__applyDefaults(this, fields, exclude, hasIncludedChildren, false, options.skipDefaults);
178
178
  }
179
179
 
180
- this.$__._id = this._id;
181
-
182
180
  if (!this.$__.strictMode && obj) {
183
181
  const _this = this;
184
182
  const keys = Object.keys(this._doc);
@@ -268,7 +266,7 @@ Document.prototype.schema;
268
266
  * is handy for passing data to middleware without conflicting with Mongoose
269
267
  * internals.
270
268
  *
271
- * ####Example:
269
+ * #### Example:
272
270
  *
273
271
  * schema.pre('save', function() {
274
272
  * // Mongoose will set `isNew` to `false` if `save()` succeeds
@@ -326,7 +324,7 @@ Document.prototype.isNew;
326
324
  /**
327
325
  * Set this property to add additional query filters when Mongoose saves this document and `isNew` is false.
328
326
  *
329
- * ####Example:
327
+ * #### Example:
330
328
  *
331
329
  * // Make sure `save()` never updates a soft deleted document.
332
330
  * schema.pre('save', function() {
@@ -348,7 +346,7 @@ Object.defineProperty(Document.prototype, '$where', {
348
346
  /**
349
347
  * The string version of this documents _id.
350
348
  *
351
- * ####Note:
349
+ * #### Note:
352
350
  *
353
351
  * This getter exists on all documents by default. The getter can be disabled by setting the `id` [option](/docs/guide.html#id) of its `Schema` to false at construction time.
354
352
  *
@@ -389,7 +387,7 @@ Document.prototype.errors;
389
387
  * A string containing the current operation that Mongoose is executing
390
388
  * on this document. May be `null`, `'save'`, `'validate'`, or `'remove'`.
391
389
  *
392
- * ####Example:
390
+ * #### Example:
393
391
  *
394
392
  * const doc = new Model({ name: 'test' });
395
393
  * doc.$op; // null
@@ -743,8 +741,6 @@ Document.prototype.$__init = function(doc, opts) {
743
741
  this.$emit('init', this);
744
742
  this.constructor.emit('init', this);
745
743
 
746
- this.$__._id = this._id;
747
-
748
744
  const hasIncludedChildren = this.$__.exclude === false && this.$__.fields ?
749
745
  $__hasIncludedChildren(this.$__.fields) :
750
746
  null;
@@ -841,11 +837,11 @@ function init(self, obj, doc, opts, prefix) {
841
837
  /**
842
838
  * Sends an update command with this document `_id` as the query selector.
843
839
  *
844
- * ####Example:
840
+ * #### Example:
845
841
  *
846
842
  * weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);
847
843
  *
848
- * ####Valid options:
844
+ * #### Valid options:
849
845
  *
850
846
  * - same as in [Model.update](#model_Model.update)
851
847
  *
@@ -876,11 +872,11 @@ Document.prototype.update = function update() {
876
872
  /**
877
873
  * Sends an updateOne command with this document `_id` as the query selector.
878
874
  *
879
- * ####Example:
875
+ * #### Example:
880
876
  *
881
877
  * weirdCar.updateOne({$inc: {wheels:1}}, { w: 1 }, callback);
882
878
  *
883
- * ####Valid options:
879
+ * #### Valid options:
884
880
  *
885
881
  * - same as in [Model.updateOne](#model_Model.updateOne)
886
882
  *
@@ -922,7 +918,7 @@ Document.prototype.updateOne = function updateOne(doc, options, callback) {
922
918
  /**
923
919
  * Sends a replaceOne command with this document `_id` as the query selector.
924
920
  *
925
- * ####Valid options:
921
+ * #### Valid options:
926
922
  *
927
923
  * - same as in [Model.replaceOne](https://mongoosejs.com/docs/api/model.html#model_Model.replaceOne)
928
924
  *
@@ -947,7 +943,7 @@ Document.prototype.replaceOne = function replaceOne() {
947
943
  * automatically set `session` if you `save()` a doc that you got from a
948
944
  * query with an associated session.
949
945
  *
950
- * ####Example:
946
+ * #### Example:
951
947
  *
952
948
  * const session = MyModel.startSession();
953
949
  * const doc = await MyModel.findOne().session(session);
@@ -1514,7 +1510,7 @@ function _isManuallyPopulatedArray(val, ref) {
1514
1510
  /**
1515
1511
  * Sets the value of a path, or many paths.
1516
1512
  *
1517
- * ####Example:
1513
+ * #### Example:
1518
1514
  *
1519
1515
  * // path, value
1520
1516
  * doc.set(path, value)
@@ -1718,7 +1714,7 @@ Document.prototype.$__setValue = function(path, val) {
1718
1714
  /**
1719
1715
  * Returns the value of a path.
1720
1716
  *
1721
- * ####Example
1717
+ * #### Example
1722
1718
  *
1723
1719
  * // path
1724
1720
  * doc.get('age') // 47
@@ -1824,7 +1820,7 @@ Document.prototype.$__path = function(path) {
1824
1820
  *
1825
1821
  * _Very helpful when using [Mixed](https://mongoosejs.com/docs/schematypes.html#mixed) types._
1826
1822
  *
1827
- * ####Example:
1823
+ * #### Example:
1828
1824
  *
1829
1825
  * doc.mixed.type = 'changed';
1830
1826
  * doc.markModified('mixed.type');
@@ -1836,6 +1832,7 @@ Document.prototype.$__path = function(path) {
1836
1832
  */
1837
1833
 
1838
1834
  Document.prototype.markModified = function(path, scope) {
1835
+ // console.log('MarkModified', path, new Error().stack);
1839
1836
  this.$__.activePaths.modify(path);
1840
1837
  if (scope != null && !this.$isSubdocument) {
1841
1838
  this.$__.pathsToScopes = this.$__pathsToScopes || {};
@@ -1846,7 +1843,7 @@ Document.prototype.markModified = function(path, scope) {
1846
1843
  /**
1847
1844
  * Clears the modified state on the specified path.
1848
1845
  *
1849
- * ####Example:
1846
+ * #### Example:
1850
1847
  *
1851
1848
  * doc.foo = 'bar';
1852
1849
  * doc.unmarkModified('foo');
@@ -1866,7 +1863,7 @@ Document.prototype.unmarkModified = function(path) {
1866
1863
  /**
1867
1864
  * Don't run validation on this path or persist changes to this path.
1868
1865
  *
1869
- * ####Example:
1866
+ * #### Example:
1870
1867
  *
1871
1868
  * doc.foo = null;
1872
1869
  * doc.$ignore('foo');
@@ -1891,7 +1888,7 @@ Document.prototype.$ignore = function(path) {
1891
1888
  * A path `a` may be in `modifiedPaths()` but not in `directModifiedPaths()`
1892
1889
  * because a child of `a` was directly modified.
1893
1890
  *
1894
- * ####Example
1891
+ * #### Example
1895
1892
  * const schema = new Schema({ foo: String, nested: { bar: String } });
1896
1893
  * const Model = mongoose.model('Test', schema);
1897
1894
  * await Model.create({ foo: 'original', nested: { bar: 'original' } });
@@ -1914,7 +1911,7 @@ Document.prototype.directModifiedPaths = function() {
1914
1911
  * Useful for determining whether this subdoc will get stripped out by the
1915
1912
  * [minimize option](/docs/guide.html#minimize).
1916
1913
  *
1917
- * ####Example:
1914
+ * #### Example:
1918
1915
  * const schema = new Schema({ nested: { foo: String } });
1919
1916
  * const Model = mongoose.model('Test', schema);
1920
1917
  * const doc = new Model({});
@@ -2047,7 +2044,7 @@ Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
2047
2044
  *
2048
2045
  * If `path` is given, checks if a path or any full path containing `path` as part of its path chain has been modified.
2049
2046
  *
2050
- * ####Example
2047
+ * #### Example
2051
2048
  *
2052
2049
  * doc.set('documents.0.title', 'changed');
2053
2050
  * doc.isModified() // true
@@ -2093,7 +2090,7 @@ Document.prototype[documentIsModified] = Document.prototype.isModified;
2093
2090
  /**
2094
2091
  * Checks if a path is set to its default.
2095
2092
  *
2096
- * ####Example
2093
+ * #### Example
2097
2094
  *
2098
2095
  * MyModel = mongoose.model('test', { name: { type: String, default: 'Val '} });
2099
2096
  * const m = new MyModel();
@@ -2127,7 +2124,7 @@ Document.prototype.$isDefault = function(path) {
2127
2124
  /**
2128
2125
  * Getter/setter, determines whether the document was removed or not.
2129
2126
  *
2130
- * ####Example:
2127
+ * #### Example:
2131
2128
  * const product = await product.remove();
2132
2129
  * product.$isDeleted(); // true
2133
2130
  * product.remove(); // no-op, doesn't send anything to the db
@@ -2157,7 +2154,7 @@ Document.prototype.$isDeleted = function(val) {
2157
2154
  /**
2158
2155
  * Returns true if `path` was directly set and modified, else false.
2159
2156
  *
2160
- * ####Example
2157
+ * #### Example
2161
2158
  *
2162
2159
  * doc.set('documents.0.title', 'changed');
2163
2160
  * doc.isDirectModified('documents.0.title') // true
@@ -2213,7 +2210,7 @@ Document.prototype.isInit = function(path) {
2213
2210
  /**
2214
2211
  * Checks if `path` was selected in the source query which initialized this document.
2215
2212
  *
2216
- * ####Example
2213
+ * #### Example
2217
2214
  *
2218
2215
  * const doc = await Thing.findOne().select('name');
2219
2216
  * doc.isSelected('name') // true
@@ -2294,7 +2291,7 @@ Document.prototype.$__isSelected = Document.prototype.isSelected;
2294
2291
  * Checks if `path` was explicitly selected. If no projection, always returns
2295
2292
  * true.
2296
2293
  *
2297
- * ####Example
2294
+ * #### Example
2298
2295
  *
2299
2296
  * Thing.findOne().select('nested.name').exec(function (err, doc) {
2300
2297
  * doc.isDirectSelected('nested.name') // true
@@ -2356,11 +2353,11 @@ Document.prototype.isDirectSelected = function isDirectSelected(path) {
2356
2353
  /**
2357
2354
  * Executes registered validation rules for this document.
2358
2355
  *
2359
- * ####Note:
2356
+ * #### Note:
2360
2357
  *
2361
2358
  * This method is called `pre` save and if a validation rule is violated, [save](#model_Model-save) is aborted and the error is returned to your `callback`.
2362
2359
  *
2363
- * ####Example:
2360
+ * #### Example:
2364
2361
  *
2365
2362
  * doc.validate(function (err) {
2366
2363
  * if (err) handleError(err);
@@ -2422,6 +2419,7 @@ Document.prototype.validate = function(pathsToValidate, options, callback) {
2422
2419
 
2423
2420
  this.$__validate(pathsToValidate, options, (error) => {
2424
2421
  this.$op = null;
2422
+ this.$__.validating = null;
2425
2423
  cb(error);
2426
2424
  });
2427
2425
  }, this.constructor.events);
@@ -2483,10 +2481,7 @@ function _getPathsToValidate(doc) {
2483
2481
  if (subdoc.$basePath) {
2484
2482
  // Remove child paths for now, because we'll be validating the whole
2485
2483
  // subdoc
2486
- if (!subdoc.$__.fullPath) {
2487
- subdoc.ownerDocument();
2488
- }
2489
- const fullPathToSubdoc = subdoc.$__.fullPath;
2484
+ const fullPathToSubdoc = subdoc.$__fullPathWithIndexes();
2490
2485
 
2491
2486
  for (const p of paths) {
2492
2487
  if (p === null || p.startsWith(fullPathToSubdoc + '.')) {
@@ -2504,12 +2499,32 @@ function _getPathsToValidate(doc) {
2504
2499
  }
2505
2500
  }
2506
2501
 
2502
+ for (const path of paths) {
2503
+ const _pathType = doc.$__schema.path(path);
2504
+ if (!_pathType) {
2505
+ continue;
2506
+ }
2507
+
2508
+ // Optimization: if primitive path with no validators, or array of primitives
2509
+ // with no validators, skip validating this path entirely.
2510
+ if (!_pathType.caster && _pathType.validators.length === 0) {
2511
+ paths.delete(path);
2512
+ } else if (_pathType.$isMongooseArray &&
2513
+ !_pathType.$isMongooseDocumentArray && // Skip document arrays...
2514
+ !_pathType.$embeddedSchemaType.$isMongooseArray && // and arrays of arrays
2515
+ _pathType.validators.length === 0 && // and arrays with top-level validators
2516
+ _pathType.$embeddedSchemaType.validators.length === 0) {
2517
+ paths.delete(path);
2518
+ }
2519
+ }
2520
+
2507
2521
  // from here on we're not removing items from paths
2508
2522
 
2509
2523
  // gh-661: if a whole array is modified, make sure to run validation on all
2510
2524
  // the children as well
2511
2525
  for (const path of paths) {
2512
2526
  const _pathType = doc.$__schema.path(path);
2527
+
2513
2528
  if (!_pathType ||
2514
2529
  !_pathType.$isMongooseArray ||
2515
2530
  // To avoid potential performance issues, skip doc arrays whose children
@@ -2616,7 +2631,8 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
2616
2631
  const _this = this;
2617
2632
  const _complete = () => {
2618
2633
  let validationError = this.$__.validationError;
2619
- this.$__.validationError = undefined;
2634
+ this.$__.validationError = null;
2635
+ this.$__.validating = null;
2620
2636
 
2621
2637
  if (shouldValidateModifiedOnly && validationError != null) {
2622
2638
  // Remove any validation errors that aren't from modified paths
@@ -2803,11 +2819,11 @@ function _handlePathsToSkip(paths, pathsToSkip) {
2803
2819
  /**
2804
2820
  * Executes registered validation rules (skipping asynchronous validators) for this document.
2805
2821
  *
2806
- * ####Note:
2822
+ * #### Note:
2807
2823
  *
2808
2824
  * This method is useful if you need synchronous validation.
2809
2825
  *
2810
- * ####Example:
2826
+ * #### Example:
2811
2827
  *
2812
2828
  * const err = doc.validateSync();
2813
2829
  * if (err) {
@@ -3042,7 +3058,7 @@ function _checkImmutableSubpaths(subdoc, schematype, priorVal) {
3042
3058
  * Saves this document by inserting a new document into the database if [document.isNew](/docs/api.html#document_Document-isNew) is `true`,
3043
3059
  * or sends an [updateOne](/docs/api.html#document_Document-updateOne) operation **only** with the modifications to the database, it does not replace the whole document in the latter case.
3044
3060
  *
3045
- * ####Example:
3061
+ * #### Example:
3046
3062
  *
3047
3063
  * product.sold = Date.now();
3048
3064
  * product = await product.save();
@@ -3050,7 +3066,7 @@ function _checkImmutableSubpaths(subdoc, schematype, priorVal) {
3050
3066
  * If save is successful, the returned promise will fulfill with the document
3051
3067
  * saved.
3052
3068
  *
3053
- * ####Example:
3069
+ * #### Example:
3054
3070
  *
3055
3071
  * const newProduct = await product.save();
3056
3072
  * newProduct === product; // true
@@ -3578,7 +3594,7 @@ Document.prototype.$toObject = function(options, json) {
3578
3594
  *
3579
3595
  * Buffers are converted to instances of [mongodb.Binary](https://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html) for proper storage.
3580
3596
  *
3581
- * ####Options:
3597
+ * #### Options:
3582
3598
  *
3583
3599
  * - `getters` apply all getters (path and virtual getters), defaults to false
3584
3600
  * - `aliases` apply all aliases if `virtuals=true`, defaults to true
@@ -3590,7 +3606,7 @@ Document.prototype.$toObject = function(options, json) {
3590
3606
  * - `flattenMaps` convert Maps to POJOs. Useful if you want to JSON.stringify() the result of toObject(), defaults to false
3591
3607
  * - `useProjection` set to `true` to omit fields that are excluded in this document's projection. Unless you specified a projection, this will omit any field that has `select: false` in the schema.
3592
3608
  *
3593
- * ####Getters/Virtuals
3609
+ * #### Getters/Virtuals
3594
3610
  *
3595
3611
  * Example of only applying path getters
3596
3612
  *
@@ -3608,7 +3624,7 @@ Document.prototype.$toObject = function(options, json) {
3608
3624
  *
3609
3625
  * schema.set('toObject', { virtuals: true })
3610
3626
  *
3611
- * ####Transform
3627
+ * #### Transform
3612
3628
  *
3613
3629
  * We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional `transform` function.
3614
3630
  *
@@ -3620,7 +3636,7 @@ Document.prototype.$toObject = function(options, json) {
3620
3636
  * - `ret` The plain object representation which has been converted
3621
3637
  * - `options` The options in use (either schema options or the options passed inline)
3622
3638
  *
3623
- * ####Example
3639
+ * #### Example
3624
3640
  *
3625
3641
  * // specify the transform schema option
3626
3642
  * if (!schema.options.toObject) schema.options.toObject = {};
@@ -4114,7 +4130,7 @@ Document.prototype.equals = function(doc) {
4114
4130
  /**
4115
4131
  * Populates paths on an existing document.
4116
4132
  *
4117
- * ####Example:
4133
+ * #### Example:
4118
4134
  *
4119
4135
  * await doc.populate([
4120
4136
  * 'stories',
@@ -4231,7 +4247,7 @@ Document.prototype.$getPopulatedDocs = function $getPopulatedDocs() {
4231
4247
  /**
4232
4248
  * Gets _id(s) used during population of the given `path`.
4233
4249
  *
4234
- * ####Example:
4250
+ * #### Example:
4235
4251
  *
4236
4252
  * Model.findOne().populate('author').exec(function (err, doc) {
4237
4253
  * console.log(doc.author.name) // Dr.Seuss
@@ -4293,7 +4309,7 @@ Document.prototype.$populated = Document.prototype.populated;
4293
4309
  /**
4294
4310
  * Takes a populated field and returns it to its unpopulated state.
4295
4311
  *
4296
- * ####Example:
4312
+ * #### Example:
4297
4313
  *
4298
4314
  * Model.findOne().populate('author').exec(function (err, doc) {
4299
4315
  * console.log(doc.author.name); // Dr.Seuss
@@ -4,7 +4,7 @@
4
4
  * MongooseError constructor. MongooseError is the base class for all
5
5
  * Mongoose-specific errors.
6
6
  *
7
- * ####Example:
7
+ * #### Example:
8
8
  * const Model = mongoose.model('Test', new Schema({ answer: Number }));
9
9
  * const doc = new Model({ answer: 'not a number' });
10
10
  * const err = doc.validateSync();
@@ -105,7 +105,7 @@ MongooseError.ValidationError = require('./validation');
105
105
  * A `ValidationError` has a hash of `errors` that contain individual
106
106
  * `ValidatorError` instances.
107
107
  *
108
- * ####Example:
108
+ * #### Example:
109
109
  *
110
110
  * const schema = Schema({ name: { type: String, required: true } });
111
111
  * const Model = mongoose.model('Test', schema);
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ const isTextIndex = require('./isTextIndex');
4
+
5
+ module.exports = function applySchemaCollation(indexKeys, indexOptions, schemaOptions) {
6
+ if (isTextIndex(indexKeys)) {
7
+ return;
8
+ }
9
+
10
+ if (schemaOptions.hasOwnProperty('collation') && !indexOptions.hasOwnProperty('collation')) {
11
+ indexOptions.collation = schemaOptions.collation;
12
+ }
13
+ };
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Returns `true` if the given index options have a `text` option.
5
+ */
6
+
7
+ module.exports = function isTextIndex(indexKeys) {
8
+ let isTextIndex = false;
9
+ for (const key of Object.keys(indexKeys)) {
10
+ if (indexKeys[key] === 'text') {
11
+ isTextIndex = true;
12
+ }
13
+ }
14
+
15
+ return isTextIndex;
16
+ };
@@ -6,7 +6,7 @@ const utils = require('../../utils');
6
6
  * If populating a path within a document array, make sure each
7
7
  * subdoc within the array knows its subpaths are populated.
8
8
  *
9
- * ####Example:
9
+ * #### Example:
10
10
  * const doc = await Article.findOne().populate('comments.author');
11
11
  * doc.comments[0].populated('author'); // Should be set
12
12
  */
@@ -4,7 +4,7 @@
4
4
  * Creates an object that precomputes whether a given path has child fields in
5
5
  * the projection.
6
6
  *
7
- * ####Example:
7
+ * #### Example:
8
8
  * const res = hasIncludedChildren({ 'a.b.c': 0 });
9
9
  * res.a; // 1
10
10
  * res['a.b']; // 1
@@ -47,7 +47,7 @@ module.exports = function castUpdate(schema, obj, options, context, filter) {
47
47
  } else if (!options.overwriteDiscriminatorKey) {
48
48
  delete obj[schema.options.discriminatorKey];
49
49
  }
50
- if (options.upsert) {
50
+ if (options.upsert && !options.overwrite) {
51
51
  moveImmutableProperties(schema, obj, context);
52
52
  }
53
53
 
@@ -217,6 +217,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
217
217
  }
218
218
 
219
219
  if (op !== '$setOnInsert' &&
220
+ !options.overwrite &&
220
221
  handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
221
222
  continue;
222
223
  }
@@ -311,6 +312,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
311
312
 
312
313
  // You can use `$setOnInsert` with immutable keys
313
314
  if (op !== '$setOnInsert' &&
315
+ !options.overwrite &&
314
316
  handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
315
317
  continue;
316
318
  }
@@ -15,7 +15,7 @@ function applyTimestampsToChildren(now, update, schema) {
15
15
  }
16
16
 
17
17
  const keys = Object.keys(update);
18
- const hasDollarKey = keys.some(key => key.startsWith('$'));
18
+ const hasDollarKey = keys.some(key => key[0] === '$');
19
19
 
20
20
  if (hasDollarKey) {
21
21
  if (update.$push) {
@@ -38,7 +38,7 @@ function applyTimestampsToChildren(now, update, schema) {
38
38
  }
39
39
  }
40
40
 
41
- const updateKeys = Object.keys(update).filter(key => !key.startsWith('$'));
41
+ const updateKeys = Object.keys(update).filter(key => key[0] !== '$');
42
42
  for (const key of updateKeys) {
43
43
  applyTimestampsToUpdateKey(schema, key, update, now);
44
44
  }
@@ -80,7 +80,6 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
80
80
  }
81
81
 
82
82
  if (!skipCreatedAt && createdAt) {
83
-
84
83
  if (currentUpdate[createdAt]) {
85
84
  delete currentUpdate[createdAt];
86
85
  }