diff --git a/.eslintrc.js b/.eslintrc.js
index 5609b0fae89..9d067d9de23 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -22,6 +22,9 @@ module.exports = {
'**/*.md/*.ts',
'**/*.md/*.typescript'
],
+ parserOptions: {
+ project: './tsconfig.json'
+ },
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended'
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 5abb3c2bb00..e22404cb71f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -27,7 +27,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
with:
- node-version: 14
+ node-version: 18
- run: npm install
@@ -39,7 +39,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- node: [14, 16, 18, 20]
+ node: [16, 18, 20]
os: [ubuntu-20.04, ubuntu-22.04]
mongodb: [4.4.18, 5.0.14, 6.0.4]
include:
@@ -108,7 +108,7 @@ jobs:
- name: Setup Deno
uses: denoland/setup-deno@v1
with:
- deno-version: v1.34.x
+ deno-version: v1.36.x
- run: deno --version
- run: npm install
- name: Run Deno tests
diff --git a/.github/workflows/tsd.yml b/.github/workflows/tsd.yml
index 5103127bec8..ca925ddc195 100644
--- a/.github/workflows/tsd.yml
+++ b/.github/workflows/tsd.yml
@@ -27,7 +27,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
with:
- node-version: 14
+ node-version: 18
- run: npm install
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f88d2188661..122ecdfdae2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+7.5.1 / 2023-09-11
+==================
+ * fix: set default value for _update when no update object is provided and versionKey is set to false #13795 #13783 [MohOraby](https://github.com/MohOraby)
+ * fix: avoid unexpected error when accessing null array element on discriminator array when populating #13716 [ZSabakh](https://github.com/ZSabakh)
+ * types(schematypes): use DocType for instance method this #13822 #13800 [pshaddel](https://github.com/pshaddel)
+ * types: remove duplicated 'exists' method in Model interface in models.d.ts #13818 [ohzeno](https://github.com/ohzeno)
+ * docs(model): replace outdated docs on deprecated findOneAndUpdate() overwrite option #13821 #13715
+ * docs: add example of using `virtuals.pathsToSkip` option for `toObject()` and `toJSON()` #13798 [RobertHunter-Pluto](https://github.com/RobertHunter-Pluto)
+
7.5.0 / 2023-08-29
==================
* feat: use mongodb driver v5.18.1
diff --git a/docs/middleware.md b/docs/middleware.md
index 433e1fb149d..923379ff9f2 100644
--- a/docs/middleware.md
+++ b/docs/middleware.md
@@ -48,7 +48,6 @@ In query middleware functions, `this` refers to the query.
* [find](api/query.html#query_Query-find)
* [findOne](api/query.html#query_Query-findOne)
* [findOneAndDelete](api/query.html#query_Query-findOneAndDelete)
-* [findOneAndRemove](api/query.html#query_Query-findOneAndRemove)
* [findOneAndReplace](api/query.html#query_Query-findOneAndReplace)
* [findOneAndUpdate](api/query.html#query_Query-findOneAndUpdate)
* [remove](api/model.html#model_Model-remove)
@@ -81,7 +80,6 @@ Here are the possible strings that can be passed to `pre()`
* find
* findOne
* findOneAndDelete
-* findOneAndRemove
* findOneAndReplace
* findOneAndUpdate
* init
diff --git a/docs/migrating_to_8.md b/docs/migrating_to_8.md
new file mode 100644
index 00000000000..b9c8cf1346a
--- /dev/null
+++ b/docs/migrating_to_8.md
@@ -0,0 +1,62 @@
+# Migrating from 7.x to 8.x
+
+
+
+There are several backwards-breaking changes
+you should be aware of when migrating from Mongoose 7.x to Mongoose 8.x.
+
+If you're still on Mongoose 6.x or earlier, please read the [Mongoose 6.x to 7.x migration guide](migrating_to_7.html) and upgrade to Mongoose 7.x first before upgrading to Mongoose 8.
+
+* [Removed `rawResult` option for `findOneAndUpdate()`](#removed-rawresult-option-for-findoneandupdate)
+* [Changed behavior for `findOneAndUpdate()` with `orFail()` and upsert](#changed-behavior-for-findoneandupdate-with-orfail-and-upsert)
+* [MongoDB Node Driver 6.0](#mongodb-node-driver-6)
+* [Removed `findOneAndRemove()`](#removed-findoneandremove)
+* [Removed id Setter](#removed-id-setter)
+
+
+
+The `rawResult` option for `findOneAndUpdate()`, `findOneAndReplace()`, and `findOneAndDelete()` has been replaced by the `includeResultMetadata` option.
+
+```javascript
+const filter = { name: 'Will Riker' };
+const update = { age: 29 };
+
+const res = await Character.findOneAndUpdate(filter, update, {
+ new: true,
+ upsert: true,
+ // Replace `rawResult: true` with `includeResultMetadata: true`
+ includeResultMetadata: true
+});
+```
+
+`includeResultMetadata` in Mongoose 8 behaves identically to `rawResult`.
+
+
+
+In Mongoose 7, `findOneAndUpdate(filter, update, { upsert: true }).orFail()` would throw a `DocumentNotFoundError` if a new document was upserted.
+In other words, `findOneAndUpdate().orFail()` always threw an error if no document was found, even if a new document was upserted.
+
+In Mongoose 8, `findOneAndUpdate(filter, update, { upsert: true }).orFail()` always succeeds.
+`findOneAndUpdate().orFail()` now throws a `DocumentNotFoundError` if there's no document returned, rather than if no document was found.
+
+
+
+Mongoose 8 uses [v6.x of the MongoDB Node driver](https://github.com/mongodb/node-mongodb-native/blob/main/HISTORY.md#600-2023-08-28).
+There's a few noteable changes in MongoDB Node driver v6 that affect Mongoose:
+
+1. The `ObjectId` constructor no longer accepts strings of length 12. In Mongoose 7, `new mongoose.Types.ObjectId('12charstring')` was perfectly valid. In Mongoose 8, `new mongoose.Types.ObjectId('12charstring')` throws an error.
+
+
+
+In Mongoose 7, `findOneAndRemove()` was an alias for `findOneAndDelete()` that Mongoose supported for backwards compatibility.
+Mongoose 8 no longer supports `findOneAndRemove()`.
+Use `findOneAndDelete()` instead.
+
+
+
+In Mongoose 7.4, Mongoose introduced an `id` setter that made `doc.id = '0'.repeat(24)` equivalent to `doc._id = '0'.repeat(24)`.
+In Mongoose 8, that setter is now removed.
\ No newline at end of file
diff --git a/docs/models.md b/docs/models.md
index b046303aa06..84c53cca0d1 100644
--- a/docs/models.md
+++ b/docs/models.md
@@ -193,7 +193,7 @@ If you attempt to `save()` a document from a View, you will get an error from th
## Yet more
-The [API docs](api/model.html#model_Model) cover many additional methods available like [count](api/model.html#model_Model-count), [mapReduce](api/model.html#model_Model-mapReduce), [aggregate](api/model.html#model_Model-aggregate), and [more](api/model.html#model_Model-findOneAndRemove).
+The [API docs](api/model.html#model_Model) cover many additional methods available like [count](api/model.html#model_Model-count), [mapReduce](api/model.html#model_Model-mapReduce), [aggregate](api/model.html#model_Model-aggregate), and more.
## Next Up
diff --git a/docs/queries.md b/docs/queries.md
index 8ca6cf1345a..27936197f6a 100644
--- a/docs/queries.md
+++ b/docs/queries.md
@@ -14,7 +14,6 @@ Each of these functions returns a
* [`Model.findByIdAndUpdate()`](api.html#model_Model-findByIdAndUpdate)
* [`Model.findOne()`](api.html#model_Model-findOne)
* [`Model.findOneAndDelete()`](api.html#model_Model-findOneAndDelete)
-* [`Model.findOneAndRemove()`](api.html#model_Model-findOneAndRemove)
* [`Model.findOneAndReplace()`](api.html#model_Model-findOneAndReplace)
* [`Model.findOneAndUpdate()`](api.html#model_Model-findOneAndUpdate)
* [`Model.replaceOne()`](api.html#model_Model-replaceOne)
diff --git a/docs/source/api.js b/docs/source/api.js
index 5c13d003d44..3aad4c04c2a 100644
--- a/docs/source/api.js
+++ b/docs/source/api.js
@@ -18,16 +18,16 @@ const files = [
'lib/cursor/QueryCursor.js',
'lib/aggregate.js',
'lib/cursor/AggregationCursor.js',
- 'lib/schematype.js',
- 'lib/virtualtype.js',
+ 'lib/schemaType.js',
+ 'lib/virtualType.js',
'lib/error/index.js',
'lib/schema/array.js',
- 'lib/schema/documentarray.js',
- 'lib/schema/SubdocumentPath.js',
+ 'lib/schema/documentArray.js',
+ 'lib/schema/subdocument.js',
'lib/schema/boolean.js',
'lib/schema/buffer.js',
'lib/schema/number.js',
- 'lib/schema/objectid.js',
+ 'lib/schema/objectId.js',
'lib/schema/string.js',
'lib/options/SchemaTypeOptions.js',
'lib/options/SchemaArrayOptions.js',
diff --git a/docs/source/index.js b/docs/source/index.js
index 1e5aaf50a6c..138853ff93a 100644
--- a/docs/source/index.js
+++ b/docs/source/index.js
@@ -65,6 +65,7 @@ docs['docs/migration.md'] = { guide: true, title: 'Migration Guide', markdown: t
docs['docs/migrating_to_5.md'] = { guide: true, title: 'Migrating to Mongoose 5', markdown: true };
docs['docs/migrating_to_6.md'] = { guide: true, title: 'Migrating to Mongoose 6', markdown: true };
docs['docs/migrating_to_7.md'] = { guide: true, title: 'Migrating to Mongoose 7', markdown: true };
+docs['docs/migrating_to_8.md'] = { guide: true, title: 'Migrating to Mongoose 8', markdown: true };
docs['docs/connections.md'] = { guide: true, title: 'Connecting to MongoDB', markdown: true };
docs['docs/lambda.md'] = { guide: true, title: 'Using Mongoose With AWS Lambda', markdown: true };
docs['docs/geojson.md'] = { guide: true, title: 'Using GeoJSON', acquit: true, markdown: true };
diff --git a/lib/browser.js b/lib/browser.js
index aef666b85a0..12b0cbde653 100644
--- a/lib/browser.js
+++ b/lib/browser.js
@@ -4,7 +4,7 @@
require('./driver').set(require('./drivers/browser'));
-const DocumentProvider = require('./document_provider.js');
+const DocumentProvider = require('./documentProvider.js');
DocumentProvider.setBrowser(true);
@@ -67,7 +67,7 @@ exports.Types = require('./types');
* @method VirtualType
* @api public
*/
-exports.VirtualType = require('./virtualtype');
+exports.VirtualType = require('./virtualType');
/**
* The various Mongoose SchemaTypes.
@@ -81,7 +81,7 @@ exports.VirtualType = require('./virtualtype');
* @api public
*/
-exports.SchemaType = require('./schematype.js');
+exports.SchemaType = require('./schemaType.js');
/**
* Internal utils
diff --git a/lib/collection.js b/lib/collection.js
index 35ddc922ef1..117a8c69551 100644
--- a/lib/collection.js
+++ b/lib/collection.js
@@ -5,7 +5,7 @@
*/
const EventEmitter = require('events').EventEmitter;
-const STATES = require('./connectionstate');
+const STATES = require('./connectionState');
const immediate = require('./helpers/immediate');
/**
diff --git a/lib/connection.js b/lib/connection.js
index 78b69c60c77..e7cf8302e87 100644
--- a/lib/connection.js
+++ b/lib/connection.js
@@ -7,7 +7,7 @@
const ChangeStream = require('./cursor/ChangeStream');
const EventEmitter = require('events').EventEmitter;
const Schema = require('./schema');
-const STATES = require('./connectionstate');
+const STATES = require('./connectionState');
const MongooseError = require('./error/index');
const ServerSelectionError = require('./error/serverSelection');
const SyncIndexesError = require('./error/syncIndexes');
diff --git a/lib/connectionstate.js b/lib/connectionState.js
similarity index 100%
rename from lib/connectionstate.js
rename to lib/connectionState.js
diff --git a/lib/cursor/QueryCursor.js b/lib/cursor/QueryCursor.js
index f59041eb51b..0d0389747e5 100644
--- a/lib/cursor/QueryCursor.js
+++ b/lib/cursor/QueryCursor.js
@@ -7,7 +7,7 @@
const MongooseError = require('../error/mongooseError');
const Readable = require('stream').Readable;
const eachAsync = require('../helpers/cursor/eachAsync');
-const helpers = require('../queryhelpers');
+const helpers = require('../queryHelpers');
const kareem = require('kareem');
const immediate = require('../helpers/immediate');
const util = require('util');
diff --git a/lib/document.js b/lib/document.js
index 773f4749a16..c31afcaca52 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -35,7 +35,7 @@ const internalToObjectOptions = require('./options').internalToObjectOptions;
const markArraySubdocsPopulated = require('./helpers/populate/markArraySubdocsPopulated');
const minimize = require('./helpers/minimize');
const mpath = require('mpath');
-const queryhelpers = require('./queryhelpers');
+const queryhelpers = require('./queryHelpers');
const utils = require('./utils');
const isPromise = require('./helpers/isPromise');
diff --git a/lib/document_provider.js b/lib/documentProvider.js
similarity index 90%
rename from lib/document_provider.js
rename to lib/documentProvider.js
index 1ace61f4fb3..894494403f4 100644
--- a/lib/document_provider.js
+++ b/lib/documentProvider.js
@@ -15,7 +15,7 @@ let isBrowser = false;
*
* @api private
*/
-module.exports = function() {
+module.exports = function documentProvider() {
if (isBrowser) {
return BrowserDocument;
}
diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index 0e6a2c29836..6898d602e12 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -6,7 +6,7 @@
const MongooseConnection = require('../../connection');
const MongooseError = require('../../error/index');
-const STATES = require('../../connectionstate');
+const STATES = require('../../connectionState');
const mongodb = require('mongodb');
const pkg = require('../../../package.json');
const processConnectionOptions = require('../../helpers/processConnectionOptions');
diff --git a/lib/helpers/discriminator/mergeDiscriminatorSchema.js b/lib/helpers/discriminator/mergeDiscriminatorSchema.js
index fcba6c231c4..b48d5c4db07 100644
--- a/lib/helpers/discriminator/mergeDiscriminatorSchema.js
+++ b/lib/helpers/discriminator/mergeDiscriminatorSchema.js
@@ -34,7 +34,8 @@ module.exports = function mergeDiscriminatorSchema(to, from, path, seen) {
key === 'base' ||
key === '_applyDiscriminators' ||
key === '_userProvidedOptions' ||
- key === 'options') {
+ key === 'options' ||
+ key === 'tree') {
continue;
}
}
@@ -73,4 +74,8 @@ module.exports = function mergeDiscriminatorSchema(to, from, path, seen) {
mergeDiscriminatorSchema(to[key], from[key], path ? path + '.' + key : key, seen);
}
}
+
+ if (from != null && from.instanceOfSchema) {
+ to.tree = Object.assign({}, from.tree, to.tree);
+ }
};
diff --git a/lib/helpers/model/applyHooks.js b/lib/helpers/model/applyHooks.js
index 7ed7895d4b3..998da62f42a 100644
--- a/lib/helpers/model/applyHooks.js
+++ b/lib/helpers/model/applyHooks.js
@@ -64,7 +64,7 @@ function applyHooks(model, schema, options) {
continue;
}
- applyHooks(childModel, type.schema, options);
+ applyHooks(childModel, type.schema, { ...options, isChildSchema: true });
if (childModel.discriminators != null) {
const keys = Object.keys(childModel.discriminators);
for (const key of keys) {
@@ -104,7 +104,8 @@ function applyHooks(model, schema, options) {
objToDecorate.$__originalValidate = objToDecorate.$__originalValidate || objToDecorate.$__validate;
- for (const method of ['save', 'validate', 'remove', 'deleteOne']) {
+ const internalMethodsToWrap = options && options.isChildSchema ? ['save', 'validate', 'deleteOne'] : ['save', 'validate'];
+ for (const method of internalMethodsToWrap) {
const toWrap = method === 'validate' ? '$__originalValidate' : `$__${method}`;
const wrapped = middleware.
createWrapper(method, objToDecorate[toWrap], null, kareemOptions);
diff --git a/lib/helpers/populate/assignRawDocsToIdStructure.js b/lib/helpers/populate/assignRawDocsToIdStructure.js
index c08671e5918..6a0cc06653c 100644
--- a/lib/helpers/populate/assignRawDocsToIdStructure.js
+++ b/lib/helpers/populate/assignRawDocsToIdStructure.js
@@ -7,7 +7,7 @@ const utils = require('../../utils');
module.exports = assignRawDocsToIdStructure;
-const kHasArray = Symbol('assignRawDocsToIdStructure.hasArray');
+const kHasArray = Symbol('mongoose#assignRawDocsToIdStructure#hasArray');
/**
* Assign `vals` returned by mongo query to the `rawIds`
diff --git a/lib/helpers/promiseOrCallback.js b/lib/helpers/promiseOrCallback.js
index 585a6486f2e..952eecf4bf8 100644
--- a/lib/helpers/promiseOrCallback.js
+++ b/lib/helpers/promiseOrCallback.js
@@ -2,7 +2,7 @@
const immediate = require('./immediate');
-const emittedSymbol = Symbol('mongoose:emitted');
+const emittedSymbol = Symbol('mongoose#emitted');
module.exports = function promiseOrCallback(callback, fn, ee, Promise) {
if (typeof callback === 'function') {
diff --git a/lib/helpers/query/completeMany.js b/lib/helpers/query/completeMany.js
index 6fab7636677..a27ecafa385 100644
--- a/lib/helpers/query/completeMany.js
+++ b/lib/helpers/query/completeMany.js
@@ -1,6 +1,6 @@
'use strict';
-const helpers = require('../../queryhelpers');
+const helpers = require('../../queryHelpers');
module.exports = completeMany;
diff --git a/lib/helpers/query/validOps.js b/lib/helpers/query/validOps.js
index f89c84264a2..2eb4375a93f 100644
--- a/lib/helpers/query/validOps.js
+++ b/lib/helpers/query/validOps.js
@@ -2,7 +2,6 @@
module.exports = Object.freeze([
// Read
- 'count',
'countDocuments',
'distinct',
'estimatedDocumentCount',
@@ -17,6 +16,5 @@ module.exports = Object.freeze([
// Delete
'deleteMany',
'deleteOne',
- 'findOneAndDelete',
- 'findOneAndRemove'
+ 'findOneAndDelete'
]);
diff --git a/lib/helpers/schema/idGetter.js b/lib/helpers/schema/idGetter.js
index 6df8a8cc04f..1fe7cc77ab3 100644
--- a/lib/helpers/schema/idGetter.js
+++ b/lib/helpers/schema/idGetter.js
@@ -16,7 +16,6 @@ module.exports = function addIdGetter(schema) {
return schema;
}
schema.virtual('id').get(idGetter);
- schema.virtual('id').set(idSetter);
return schema;
};
@@ -33,14 +32,3 @@ function idGetter() {
return null;
}
-
-/**
- *
- * @param {String} v the id to set
- * @api private
- */
-
-function idSetter(v) {
- this._id = v;
- return v;
-}
diff --git a/lib/helpers/symbols.js b/lib/helpers/symbols.js
index f12db3d8272..a9af890a5d6 100644
--- a/lib/helpers/symbols.js
+++ b/lib/helpers/symbols.js
@@ -5,7 +5,7 @@ exports.arrayAtomicsSymbol = Symbol('mongoose#Array#_atomics');
exports.arrayParentSymbol = Symbol('mongoose#Array#_parent');
exports.arrayPathSymbol = Symbol('mongoose#Array#_path');
exports.arraySchemaSymbol = Symbol('mongoose#Array#_schema');
-exports.documentArrayParent = Symbol('mongoose:documentArrayParent');
+exports.documentArrayParent = Symbol('mongoose#documentArrayParent');
exports.documentIsSelected = Symbol('mongoose#Document#isSelected');
exports.documentIsModified = Symbol('mongoose#Document#isModified');
exports.documentModifiedPaths = Symbol('mongoose#Document#modifiedPaths');
@@ -13,8 +13,8 @@ exports.documentSchemaSymbol = Symbol('mongoose#Document#schema');
exports.getSymbol = Symbol('mongoose#Document#get');
exports.modelSymbol = Symbol('mongoose#Model');
exports.objectIdSymbol = Symbol('mongoose#ObjectId');
-exports.populateModelSymbol = Symbol('mongoose.PopulateOptions#Model');
+exports.populateModelSymbol = Symbol('mongoose#PopulateOptions#Model');
exports.schemaTypeSymbol = Symbol('mongoose#schemaType');
-exports.sessionNewDocuments = Symbol('mongoose:ClientSession#newDocuments');
+exports.sessionNewDocuments = Symbol('mongoose#ClientSession#newDocuments');
exports.scopeSymbol = Symbol('mongoose#Document#scope');
-exports.validatorErrorSymbol = Symbol('mongoose:validatorError');
+exports.validatorErrorSymbol = Symbol('mongoose#validatorError');
diff --git a/lib/index.js b/lib/index.js
index 6c551ae5dfa..d251828e4f3 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -10,11 +10,11 @@ const Document = require('./document');
const EventEmitter = require('events').EventEmitter;
const Kareem = require('kareem');
const Schema = require('./schema');
-const SchemaType = require('./schematype');
+const SchemaType = require('./schemaType');
const SchemaTypes = require('./schema/index');
-const VirtualType = require('./virtualtype');
-const STATES = require('./connectionstate');
-const VALID_OPTIONS = require('./validoptions');
+const VirtualType = require('./virtualType');
+const STATES = require('./connectionState');
+const VALID_OPTIONS = require('./validOptions');
const Types = require('./types');
const Query = require('./query');
const Model = require('./model');
@@ -981,7 +981,7 @@ Mongoose.prototype.Document = Document;
* @api public
*/
-Mongoose.prototype.DocumentProvider = require('./document_provider');
+Mongoose.prototype.DocumentProvider = require('./documentProvider');
/**
* The Mongoose ObjectId [SchemaType](https://mongoosejs.com/docs/schematypes.html). Used for
diff --git a/lib/internal.js b/lib/internal.js
index c4445c254d6..8de1b278773 100644
--- a/lib/internal.js
+++ b/lib/internal.js
@@ -4,7 +4,7 @@
'use strict';
-const StateMachine = require('./statemachine');
+const StateMachine = require('./stateMachine');
const ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default', 'ignore');
module.exports = exports = InternalCache;
diff --git a/lib/model.js b/lib/model.js
index b01464ad296..3a67d4578e8 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -10,6 +10,7 @@ const Document = require('./document');
const DocumentNotFoundError = require('./error/notFound');
const DivergentArrayError = require('./error/divergentArray');
const EventEmitter = require('events').EventEmitter;
+const Kareem = require('kareem');
const MongooseBuffer = require('./types/buffer');
const MongooseError = require('./error/index');
const OverwriteModelError = require('./error/overwriteModel');
@@ -61,7 +62,7 @@ const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscrim
const pushNestedArrayPaths = require('./helpers/model/pushNestedArrayPaths');
const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField');
const setDottedPath = require('./helpers/path/setDottedPath');
-const STATES = require('./connectionstate');
+const STATES = require('./connectionState');
const util = require('util');
const utils = require('./utils');
const MongooseBulkWriteError = require('./error/bulkWriteError');
@@ -1004,18 +1005,18 @@ Model.prototype.$__where = function _where(where) {
};
/**
- * Removes this document from the db. Equivalent to `.remove()`.
+ * Delete this document from the db.
*
* #### Example:
*
- * product = await product.deleteOne();
+ * await product.deleteOne();
* await Product.findById(product._id); // null
*
- * @return {Promise} Promise
+ * @return {Query} Query
* @api public
*/
-Model.prototype.deleteOne = async function deleteOne(options) {
+Model.prototype.deleteOne = function deleteOne(options) {
if (typeof options === 'function' ||
typeof arguments[1] === 'function') {
throw new MongooseError('Model.prototype.deleteOne() no longer accepts a callback');
@@ -1029,51 +1030,43 @@ Model.prototype.deleteOne = async function deleteOne(options) {
this.$session(options.session);
}
- const res = await new Promise((resolve, reject) => {
- this.$__deleteOne(options, (err, res) => {
- if (err != null) {
- return reject(err);
- }
- resolve(res);
- });
- });
-
- return res;
-};
-
-/*!
- * ignore
- */
-
-Model.prototype.$__deleteOne = function $__deleteOne(options, cb) {
- if (this.$__.isDeleted) {
- return immediate(() => cb(null, this));
- }
-
+ const self = this;
const where = this.$__where();
- if (where instanceof MongooseError) {
- return cb(where);
+ if (where instanceof Error) {
+ throw where;
}
+ const query = self.constructor.deleteOne(where, options);
- _applyCustomWhere(this, where);
-
- const session = this.$session();
- if (!options.hasOwnProperty('session')) {
- options.session = session;
+ if (this.$session() != null) {
+ if (!('session' in query.options)) {
+ query.options.session = this.$session();
+ }
}
- this[modelCollectionSymbol].deleteOne(where, options).then(
- () => {
- this.$__.isDeleted = true;
- this.$emit('deleteOne', this);
- this.constructor.emit('deleteOne', this);
- return cb(null, this);
- },
- err => {
- this.$__.isDeleted = false;
- cb(err);
+ query.pre(function queryPreDeleteOne(cb) {
+ self.constructor._middleware.execPre('deleteOne', self, [self], cb);
+ });
+ query.pre(function callSubdocPreHooks(cb) {
+ each(self.$getAllSubdocs(), (subdoc, cb) => {
+ subdoc.constructor._middleware.execPre('deleteOne', subdoc, [subdoc], cb);
+ }, cb);
+ });
+ query.pre(function skipIfAlreadyDeleted(cb) {
+ if (self.$__.isDeleted) {
+ return cb(Kareem.skipWrappedFunction());
}
- );
+ return cb();
+ });
+ query.post(function callSubdocPostHooks(cb) {
+ each(self.$getAllSubdocs(), (subdoc, cb) => {
+ subdoc.constructor._middleware.execPost('deleteOne', subdoc, [subdoc], {}, cb);
+ }, cb);
+ });
+ query.post(function queryPostDeleteOne(cb) {
+ self.constructor._middleware.execPost('deleteOne', self, [self], {}, cb);
+ });
+
+ return query;
};
/**
@@ -1468,6 +1461,17 @@ Model.createCollection = async function createCollection(options) {
* // Will drop the 'age' index and create an index on `name`
* await Customer.syncIndexes();
*
+ * You should be careful about running `syncIndexes()` on production applications under heavy load,
+ * because index builds are expensive operations, and unexpected index drops can lead to degraded
+ * performance. Before running `syncIndexes()`, you can use the [`diffIndexes()` function](#Model.diffIndexes())
+ * to check what indexes `syncIndexes()` will drop and create.
+ *
+ * #### Example:
+ *
+ * const { toDrop, toCreate } = await Model.diffIndexes();
+ * toDrop; // Array of strings containing names of indexes that `syncIndexes()` will drop
+ * toCreate; // Array of strings containing names of indexes that `syncIndexes()` will create
+ *
* @param {Object} [options] options to pass to `ensureIndexes()`
* @param {Boolean} [options.background=null] if specified, overrides each index's `background` property
* @return {Promise}
@@ -1500,9 +1504,14 @@ Model.syncIndexes = async function syncIndexes(options) {
/**
* Does a dry-run of `Model.syncIndexes()`, returning the indexes that `syncIndexes()` would drop and create if you were to run `syncIndexes()`.
*
+ * #### Example:
+ *
+ * const { toDrop, toCreate } = await Model.diffIndexes();
+ * toDrop; // Array of strings containing names of indexes that `syncIndexes()` will drop
+ * toCreate; // Array of strings containing names of indexes that `syncIndexes()` will create
+ *
* @param {Object} [options]
- * @returns {Promise} which contains an object, {toDrop, toCreate}, which
- * are indexes that would be dropped in MongoDB and indexes that would be created in MongoDB.
+ * @return {Promise} contains the indexes that would be dropped in MongoDB and indexes that would be created in MongoDB as `{ toDrop: string[], toCreate: string[] }`.
*/
Model.diffIndexes = async function diffIndexes() {
@@ -2257,34 +2266,6 @@ Model.countDocuments = function countDocuments(conditions, options) {
return mq.countDocuments(conditions);
};
-/**
- * Counts number of documents that match `filter` in a database collection.
- *
- * This method is deprecated. If you want to count the number of documents in
- * a collection, e.g. `count({})`, use the [`estimatedDocumentCount()` function](https://mongoosejs.com/docs/api/model.html#Model.estimatedDocumentCount())
- * instead. Otherwise, use the [`countDocuments()`](https://mongoosejs.com/docs/api/model.html#Model.countDocuments()) function instead.
- *
- * #### Example:
- *
- * const count = await Adventure.count({ type: 'jungle' });
- * console.log('there are %d jungle adventures', count);
- *
- * @deprecated
- * @param {Object} [filter]
- * @return {Query}
- * @api public
- */
-
-Model.count = function count(conditions) {
- _checkContext(this, 'count');
- if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function') {
- throw new MongooseError('Model.count() no longer accepts a callback');
- }
-
- const mq = new this.Query({}, {}, this, this.$__collection);
-
- return mq.count(conditions);
-};
/**
* Creates a Query for a `distinct` operation.
@@ -2417,7 +2398,7 @@ Model.$where = function $where() {
* @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
* @param {Boolean} [options.runValidators] if true, runs [update validators](https://mongoosejs.com/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema
* @param {Boolean} [options.setDefaultsOnInsert=true] If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * @param {Boolean} [options.includeResultMetadata] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Tutorial https://mongoosejs.com/docs/tutorials/findoneandupdate.html
@@ -2533,7 +2514,7 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
* @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
* @param {Boolean} [options.runValidators] if true, runs [update validators](https://mongoosejs.com/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema
* @param {Boolean} [options.setDefaultsOnInsert=true] If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * @param {Boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
* @param {Boolean} [options.new=false] if true, return the modified document rather than the original
* @param {Object|String} [options.select] sets the document fields to return.
@@ -2567,12 +2548,6 @@ Model.findByIdAndUpdate = function(id, update, options) {
*
* - `findOneAndDelete()`
*
- * This function differs slightly from `Model.findOneAndRemove()` in that
- * `findOneAndRemove()` becomes a [MongoDB `findAndModify()` command](https://www.mongodb.com/docs/manual/reference/method/db.collection.findAndModify/),
- * as opposed to a `findOneAndDelete()` command. For most mongoose use cases,
- * this distinction is purely pedantic. You should use `findOneAndDelete()`
- * unless you have a good reason not to.
- *
* #### Example:
*
* A.findOneAndDelete(conditions, options) // return Query
@@ -2594,7 +2569,7 @@ Model.findByIdAndUpdate = function(id, update, options) {
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @param {Object|String|String[]} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * @param {Boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
* @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
* @param {Object|String} [options.select] sets the document fields to return.
* @param {Number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
@@ -2636,7 +2611,7 @@ Model.findOneAndDelete = function(conditions, options) {
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
- * @see Model.findOneAndRemove https://mongoosejs.com/docs/api/model.html#Model.findOneAndRemove()
+ * @see Model.findOneAndDelete https://mongoosejs.com/docs/api/model.html#Model.findOneAndDelete()
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
@@ -2675,7 +2650,7 @@ Model.findByIdAndDelete = function(id, options) {
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
* @param {Object|String|String[]} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
* @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * @param {Boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
* @param {Object|String} [options.select] sets the document fields to return.
* @param {Number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
@@ -2702,104 +2677,6 @@ Model.findOneAndReplace = function(filter, replacement, options) {
return mq.findOneAndReplace(filter, replacement, options);
};
-/**
- * Issue a mongodb findOneAndRemove command.
- *
- * Finds a matching document, removes it, and returns the found document (if any).
- *
- * This function triggers the following middleware.
- *
- * - `findOneAndRemove()`
- *
- * #### Example:
- *
- * A.findOneAndRemove(conditions, options) // return Query
- * A.findOneAndRemove(conditions) // returns Query
- * A.findOneAndRemove() // returns Query
- *
- * `findOneAndX` and `findByIdAndX` functions support limited validation. You can
- * enable validation by setting the `runValidators` option.
- *
- * If you need full-fledged validation, use the traditional approach of first
- * retrieving the document.
- *
- * const doc = await Model.findById(id);
- * doc.name = 'jason bourne';
- * await doc.save();
- *
- * @param {Object} conditions
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
- * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
- * @param {Object|String|String[]} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
- * @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
- * @param {Object|String} [options.select] sets the document fields to return.
- * @param {Number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
- * @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
- * @return {Query}
- * @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
- * @api public
- */
-
-Model.findOneAndRemove = function(conditions, options) {
- _checkContext(this, 'findOneAndRemove');
-
- if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function' || typeof arguments[3] === 'function') {
- throw new MongooseError('Model.findOneAndRemove() no longer accepts a callback');
- }
-
- let fields;
- if (options) {
- fields = options.select;
- options.select = undefined;
- }
-
- const mq = new this.Query({}, {}, this, this.$__collection);
- mq.select(fields);
-
- return mq.findOneAndRemove(conditions, options);
-};
-
-/**
- * Issue a mongodb findOneAndRemove command by a document's _id field. `findByIdAndRemove(id, ...)` is equivalent to `findOneAndRemove({ _id: id }, ...)`.
- *
- * Finds a matching document, removes it, and returns the found document (if any).
- *
- * This function triggers the following middleware.
- *
- * - `findOneAndRemove()`
- *
- * #### Example:
- *
- * A.findByIdAndRemove(id, options) // return Query
- * A.findByIdAndRemove(id) // returns Query
- * A.findByIdAndRemove() // returns Query
- *
- * @param {Object|Number|String} id value of `_id` to query by
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
- * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
- * @param {Object|String|String[]} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
- * @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
- * @param {Object|String} [options.select] sets the document fields to return.
- * @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
- * @return {Query}
- * @see Model.findOneAndRemove https://mongoosejs.com/docs/api/model.html#Model.findOneAndRemove()
- * @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
- */
-
-Model.findByIdAndRemove = function(id, options) {
- _checkContext(this, 'findByIdAndRemove');
-
- if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function' || typeof arguments[3] === 'function') {
- throw new MongooseError('Model.findByIdAndRemove() no longer accepts a callback');
- }
-
- return this.findOneAndRemove({ _id: id }, options);
-};
-
/**
* Shortcut for saving one or more documents to the database.
* `MyModel.create(docs)` does `new MyModel(doc).save()` for every doc in
@@ -2913,16 +2790,14 @@ Model.create = async function create(doc, options) {
}
}
return res;
- } else {
- // ".bind(Promise)" is required, otherwise results in "TypeError: Promise.allSettled called on non-object"
- const promiseType = !immediateError ? Promise.allSettled.bind(Promise) : Promise.all.bind(Promise);
- let p = promiseType(args.map(async doc => {
+ } else if (!immediateError) {
+ res = await Promise.allSettled(args.map(async doc => {
const Model = this.discriminators && doc[discriminatorKey] != null ?
this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :
this;
if (Model == null) {
throw new MongooseError(`Discriminator "${doc[discriminatorKey]}" not ` +
- `found for model "${this.modelName}"`);
+ `found for model "${this.modelName}"`);
}
let toSave = doc;
@@ -2934,13 +2809,36 @@ Model.create = async function create(doc, options) {
return toSave;
}));
+ res = res.map(result => result.status === 'fulfilled' ? result.value : result.reason);
+ } else {
+ let firstError = null;
+ res = await Promise.all(args.map(async doc => {
+ const Model = this.discriminators && doc[discriminatorKey] != null ?
+ this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :
+ this;
+ if (Model == null) {
+ throw new MongooseError(`Discriminator "${doc[discriminatorKey]}" not ` +
+ `found for model "${this.modelName}"`);
+ }
+ try {
+ let toSave = doc;
- // chain the mapper, only if "allSettled" is used
- if (!immediateError) {
- p = p.then(presult => presult.map(v => v.status === 'fulfilled' ? v.value : v.reason));
- }
+ if (!(toSave instanceof Model)) {
+ toSave = new Model(toSave);
+ }
+
+ await toSave.$save(options);
- res = await p;
+ return toSave;
+ } catch (err) {
+ if (!firstError) {
+ firstError = err;
+ }
+ }
+ }));
+ if (firstError) {
+ throw firstError;
+ }
}
@@ -3861,7 +3759,7 @@ Model.hydrate = function(obj, projection, options) {
obj = applyProjection(obj, projection);
}
- const document = require('./queryhelpers').createModel(this, obj, projection);
+ const document = require('./queryHelpers').createModel(this, obj, projection);
document.$init(obj, options);
return document;
};
@@ -4102,7 +4000,7 @@ Model.aggregate = function aggregate(pipeline, options) {
* @param {Object} obj
* @param {Object|Array|String} pathsOrOptions
* @param {Object} [context]
- * @return {Promise|undefined}
+ * @return {Promise} casted and validated copy of `obj` if validation succeeded
* @api public
*/
@@ -4161,8 +4059,19 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
pushNestedArrayPaths(paths, val, path);
}
- let remaining = paths.length;
let error = null;
+ paths = new Set(paths);
+
+ try {
+ obj = this.castObject(obj);
+ } catch (err) {
+ error = err;
+ for (const key of Object.keys(error.errors || {})) {
+ paths.delete(key);
+ }
+ }
+
+ let remaining = paths.size;
return new Promise((resolve, reject) => {
for (const path of paths) {
@@ -4178,20 +4087,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
cur = cur[pieces[i]];
}
- let val = get(obj, path, void 0);
-
- if (val != null) {
- try {
- val = schemaType.cast(val);
- cur[pieces[pieces.length - 1]] = val;
- } catch (err) {
- error = error || new ValidationError();
- error.addError(path, err);
-
- _checkDone();
- continue;
- }
- }
+ const val = get(obj, path, void 0);
schemaType.doValidate(val, err => {
if (err) {
@@ -4207,7 +4103,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
if (error) {
reject(error);
} else {
- resolve();
+ resolve(obj);
}
}
}
diff --git a/lib/plugins/index.js b/lib/plugins/index.js
index 69fa6ad284c..a8a6c044240 100644
--- a/lib/plugins/index.js
+++ b/lib/plugins/index.js
@@ -1,6 +1,5 @@
'use strict';
-exports.removeSubdocs = require('./removeSubdocs');
exports.saveSubdocs = require('./saveSubdocs');
exports.sharding = require('./sharding');
exports.trackTransaction = require('./trackTransaction');
diff --git a/lib/plugins/removeSubdocs.js b/lib/plugins/removeSubdocs.js
deleted file mode 100644
index 85c7de0ff20..00000000000
--- a/lib/plugins/removeSubdocs.js
+++ /dev/null
@@ -1,35 +0,0 @@
-'use strict';
-
-const each = require('../helpers/each');
-
-/*!
- * ignore
- */
-
-module.exports = function removeSubdocs(schema) {
- const unshift = true;
- schema.s.hooks.pre('deleteOne', { document: true, query: false }, function removeSubDocsPreRemove(next) {
- if (this.$isSubdocument) {
- next();
- return;
- }
- if (this.$__ == null) {
- next();
- return;
- }
-
- const _this = this;
- const subdocs = this.$getAllSubdocs();
-
- each(subdocs, function(subdoc, cb) {
- subdoc.$__deleteOne(cb);
- }, function(error) {
- if (error) {
- return _this.$__schema.s.hooks.execPost('deleteOne:error', _this, [_this], { error: error }, function(error) {
- next(error);
- });
- }
- next();
- });
- }, null, unshift);
-};
diff --git a/lib/query.js b/lib/query.js
index 8afac05cae1..0e33882933d 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -22,7 +22,7 @@ const clone = require('./helpers/clone');
const completeMany = require('./helpers/query/completeMany');
const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue');
const hasDollarKeys = require('./helpers/query/hasDollarKeys');
-const helpers = require('./queryhelpers');
+const helpers = require('./queryHelpers');
const immediate = require('./helpers/immediate');
const internalToObjectOptions = require('./options').internalToObjectOptions;
const isExclusive = require('./helpers/projection/isExclusive');
@@ -37,6 +37,7 @@ const sanitizeFilter = require('./helpers/query/sanitizeFilter');
const sanitizeProjection = require('./helpers/query/sanitizeProjection');
const selectPopulatedFields = require('./helpers/query/selectPopulatedFields');
const setDefaultsOnInsert = require('./helpers/setDefaultsOnInsert');
+const specialProperties = require('./helpers/specialProperties');
const updateValidators = require('./helpers/updateValidators');
const util = require('util');
const utils = require('./utils');
@@ -1218,7 +1219,6 @@ Query.prototype.toString = function toString() {
this.op === 'deleteMany' ||
this.op === 'deleteOne' ||
this.op === 'findOneAndDelete' ||
- this.op === 'findOneAndRemove' ||
this.op === 'remove') {
return `${this.model.modelName}.${this.op}(${util.inspect(this._conditions)})`;
}
@@ -1549,13 +1549,13 @@ Query.prototype.getOptions = function() {
*
* - [maxTimeMS](https://www.mongodb.com/docs/manual/reference/operator/meta/maxTimeMS/)
*
- * The following options are for `find()`, `findOne()`, `findOneAndUpdate()`, `findOneAndRemove()`, `findOneAndDelete()`, `updateOne()`, and `deleteOne()`:
+ * The following options are for `find()`, `findOne()`, `findOneAndUpdate()`, `findOneAndDelete()`, `updateOne()`, and `deleteOne()`:
*
* - [sort](https://www.mongodb.com/docs/manual/reference/method/cursor.sort/)
*
- * The following options are for `findOneAndUpdate()` and `findOneAndRemove()`
+ * The following options are for `findOneAndUpdate()` and `findOneAndDelete()`
*
- * - rawResult
+ * - includeResultMetadata
*
* The following options are for all operations:
*
@@ -1636,10 +1636,6 @@ Query.prototype.setOptions = function(options, overwrite) {
delete options.translateAliases;
}
- if ('rawResult' in options) {
- printRawResultDeprecationWarning();
- }
-
if (options.lean == null && this.schema && 'lean' in this.schema.options) {
this._mongooseOptions.lean = this.schema.options.lean;
}
@@ -1674,15 +1670,6 @@ Query.prototype.setOptions = function(options, overwrite) {
return this;
};
-/*!
- * ignore
- */
-
-const printRawResultDeprecationWarning = util.deprecate(
- function printRawResultDeprecationWarning() {},
- 'The `rawResult` option for Mongoose queries is deprecated. Use `includeResultMetadata: false` as a replacement for `rawResult: true`.'
-);
-
/*!
* ignore
*/
@@ -2349,8 +2336,6 @@ Query.prototype.find = function(conditions) {
this.error(new ObjectParameterError(conditions, 'filter', 'find'));
}
- Query.base.find.call(this);
-
return this;
};
@@ -2456,7 +2441,7 @@ Query.prototype.collation = function(value) {
*/
Query.prototype._completeOne = function(doc, res, callback) {
- if (!doc && !this.options.rawResult && !this.options.includeResultMetadata) {
+ if (!doc && !this.options.includeResultMetadata) {
return callback(null, null);
}
@@ -2465,7 +2450,7 @@ Query.prototype._completeOne = function(doc, res, callback) {
const userProvidedFields = this._userProvidedFields || {};
// `populate`, `lean`
const mongooseOptions = this._mongooseOptions;
- // `rawResult`
+
const options = this.options;
if (!options.lean && mongooseOptions.lean) {
options.lean = mongooseOptions.lean;
@@ -2598,40 +2583,9 @@ Query.prototype.findOne = function(conditions, projection, options) {
this.error(new ObjectParameterError(conditions, 'filter', 'findOne'));
}
- Query.base.findOne.call(this);
-
return this;
};
-/**
- * Execute a count query
- *
- * @see count https://www.mongodb.com/docs/manual/reference/method/db.collection.count/
- * @api private
- */
-
-Query.prototype._count = async function _count() {
- try {
- this.cast(this.model);
- } catch (err) {
- this.error(err);
- }
-
- if (this.error()) {
- throw this.error();
- }
-
- applyGlobalMaxTimeMS(this.options, this.model);
- applyGlobalDiskUse(this.options, this.model);
-
- const options = this._optionsForExec();
-
- this._applyTranslateAliases(options);
-
- const conds = this._conditions;
-
- return this._collection.collection.count(conds, options);
-};
/**
* Execute a countDocuments query
@@ -2708,50 +2662,6 @@ Query.prototype._estimatedDocumentCount = async function _estimatedDocumentCount
return this._collection.collection.estimatedDocumentCount(options);
};
-/**
- * Specifies this query as a `count` query.
- *
- * This method is deprecated. If you want to count the number of documents in
- * a collection, e.g. `count({})`, use the [`estimatedDocumentCount()` function](https://mongoosejs.com/docs/api/query.html#Query.prototype.estimatedDocumentCount())
- * instead. Otherwise, use the [`countDocuments()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.countDocuments()) function instead.
- *
- * This function triggers the following middleware.
- *
- * - `count()`
- *
- * #### Example:
- *
- * const countQuery = model.where({ 'color': 'black' }).count();
- *
- * query.count({ color: 'black' }).count().exec();
- *
- * await query.count({ color: 'black' });
- *
- * query.where('color', 'black').count();
- *
- * @deprecated
- * @param {Object} [filter] count documents that match this object
- * @return {Query} this
- * @see count https://www.mongodb.com/docs/manual/reference/method/db.collection.count/
- * @api public
- */
-
-Query.prototype.count = function(filter) {
- if (typeof filter === 'function' ||
- typeof arguments[1] === 'function') {
- throw new MongooseError('Query.prototype.count() no longer accepts a callback');
- }
-
- this.op = 'count';
- this._validateOp();
-
- if (mquery.canMerge(filter)) {
- this.merge(filter);
- }
-
- return this;
-};
-
/**
* Specifies this query as a `estimatedDocumentCount()` query. Faster than
* using `countDocuments()` for large collections because
@@ -2952,9 +2862,72 @@ Query.prototype.sort = function(arg) {
throw new Error('sort() only takes 1 Argument');
}
- return Query.base.sort.call(this, arg);
+ if (this.options.sort == null) {
+ this.options.sort = {};
+ }
+ const sort = this.options.sort;
+ if (typeof arg === 'string') {
+ const properties = arg.indexOf(' ') === -1 ? [arg] : arg.split(' ');
+ for (let property of properties) {
+ const ascend = '-' == property[0] ? -1 : 1;
+ if (ascend === -1) {
+ property = property.slice(1);
+ }
+ if (specialProperties.has(property)) {
+ continue;
+ }
+ sort[property] = ascend;
+ }
+ } else if (Array.isArray(arg)) {
+ for (const pair of arg) {
+ if (!Array.isArray(pair)) {
+ throw new TypeError('Invalid sort() argument, must be array of arrays');
+ }
+ const key = '' + pair[0];
+ if (specialProperties.has(key)) {
+ continue;
+ }
+ sort[key] = _handleSortValue(pair[1], key);
+ }
+ } else if (typeof arg === 'object' && arg != null && !(arg instanceof Map)) {
+ for (const key of Object.keys(arg)) {
+ if (specialProperties.has(key)) {
+ continue;
+ }
+ sort[key] = _handleSortValue(arg[key], key);
+ }
+ } else if (arg instanceof Map) {
+ for (let key of arg.keys()) {
+ key = '' + key;
+ if (specialProperties.has(key)) {
+ continue;
+ }
+ sort[key] = _handleSortValue(arg.get(key), key);
+ }
+ } else if (arg != null) {
+ throw new TypeError('Invalid sort() argument. Must be a string, object, array, or map.');
+ }
+
+ return this;
};
+/*!
+ * Convert sort values
+ */
+
+function _handleSortValue(val, key) {
+ if (val === 1 || val === 'asc' || val === 'ascending') {
+ return 1;
+ }
+ if (val === -1 || val === 'desc' || val === 'descending') {
+ return -1;
+ }
+ if (val?.$meta != null) {
+ return { $meta: val.$meta };
+ }
+ throw new TypeError('Invalid sort value: { ' + key + ': ' + val + ' }');
+}
+
/**
* Declare and/or execute this query as a `deleteOne()` operation. Works like
* remove, except it deletes at most one document regardless of the `single`
@@ -3003,8 +2976,6 @@ Query.prototype.deleteOne = function deleteOne(filter, options) {
this.error(new ObjectParameterError(filter, 'filter', 'deleteOne'));
}
- Query.base.deleteOne.call(this);
-
return this;
};
@@ -3078,8 +3049,6 @@ Query.prototype.deleteMany = function(filter, options) {
this.error(new ObjectParameterError(filter, 'filter', 'deleteMany'));
}
- Query.base.deleteMany.call(this);
-
return this;
};
@@ -3120,7 +3089,7 @@ Query.prototype._deleteMany = async function _deleteMany() {
*/
function completeOne(model, doc, res, options, fields, userProvidedFields, pop, callback) {
- if ((options.rawResult || options.includeResultMetadata) && doc == null) {
+ if (options.includeResultMetadata && doc == null) {
_init(null);
return null;
}
@@ -3133,7 +3102,7 @@ function completeOne(model, doc, res, options, fields, userProvidedFields, pop,
}
- if (options.rawResult || options.includeResultMetadata) {
+ if (options.includeResultMetadata) {
if (doc && casted) {
if (options.session != null) {
casted.$session(options.session);
@@ -3188,7 +3157,6 @@ function prepareDiscriminatorCriteria(query) {
* - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
* - `runValidators`: if true, runs [update validators](https://mongoosejs.com/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
* - `setDefaultsOnInsert`: `true` by default. If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created.
- * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
*
* #### Example:
*
@@ -3203,7 +3171,7 @@ function prepareDiscriminatorCriteria(query) {
* @param {Object|Query} [filter]
* @param {Object} [doc]
* @param {Object} [options]
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * @param {Boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
* @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors.
@@ -3312,10 +3280,6 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
applyGlobalMaxTimeMS(this.options, this.model);
applyGlobalDiskUse(this.options, this.model);
- if (this.options.rawResult && this.options.includeResultMetadata === false) {
- throw new MongooseError('Cannot set `rawResult` option when `includeResultMetadata` is false');
- }
-
if ('strict' in this.options) {
this._mongooseOptions.strict = this.options.strict;
}
@@ -3366,7 +3330,7 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
for (const fn of this._transforms) {
res = fn(res);
}
- const doc = options.includeResultMetadata === false ? res : res.value;
+ const doc = !options.includeResultMetadata ? res : res.value;
return new Promise((resolve, reject) => {
this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => {
@@ -3378,60 +3342,6 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
});
};
-/**
- * Legacy alias for `findOneAndDelete()`.
- *
- * Finds a matching document, removes it, returns the found document (if any).
- *
- * This function triggers the following middleware.
- *
- * - `findOneAndRemove()`
- *
- * #### Available options
- *
- * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
- * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
- * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
- *
- * #### Example:
- *
- * A.where().findOneAndRemove(conditions, options) // return Query
- * A.where().findOneAndRemove(conditions) // returns Query
- * A.where().findOneAndRemove() // returns Query
- *
- * @method findOneAndRemove
- * @memberOf Query
- * @instance
- * @param {Object} [conditions]
- * @param {Object} [options]
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
- * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
- * @return {Query} this
- * @see findAndModify command https://www.mongodb.com/docs/manual/reference/command/findAndModify/
- * @api public
- */
-
-Query.prototype.findOneAndRemove = function(conditions, options) {
- if (typeof conditions === 'function' ||
- typeof options === 'function' ||
- typeof arguments[2] === 'function') {
- throw new MongooseError('Query.prototype.findOneAndRemove() no longer accepts a callback');
- }
-
- this.op = 'findOneAndRemove';
- this._validateOp();
- this._validate();
-
- if (mquery.canMerge(conditions)) {
- this.merge(conditions);
- }
-
- options && this.setOptions(options);
-
- return this;
-};
-
/**
* Issues a MongoDB [findOneAndDelete](https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndDelete/) command.
*
@@ -3445,7 +3355,6 @@ Query.prototype.findOneAndRemove = function(conditions, options) {
*
* - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
* - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
- * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
*
* #### Callback Signature
*
@@ -3464,7 +3373,7 @@ Query.prototype.findOneAndRemove = function(conditions, options) {
* @memberOf Query
* @param {Object} [filter]
* @param {Object} [options]
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * @param {Boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @return {Query} this
@@ -3508,9 +3417,6 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() {
}
const includeResultMetadata = this.options.includeResultMetadata;
- if (this.options.rawResult && includeResultMetadata === false) {
- throw new MongooseError('Cannot set `rawResult` option when `includeResultMetadata` is false');
- }
const filter = this._conditions;
const options = this._optionsForExec(this.model);
@@ -3520,7 +3426,7 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() {
for (const fn of this._transforms) {
res = fn(res);
}
- const doc = includeResultMetadata === false ? res : res.value;
+ const doc = !includeResultMetadata ? res : res.value;
return new Promise((resolve, reject) => {
this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => {
@@ -3545,7 +3451,7 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() {
*
* - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
* - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
- * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * - `includeResultMetadata`: if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
*
* #### Callback Signature
*
@@ -3565,7 +3471,7 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() {
* @param {Object} [filter]
* @param {Object} [replacement]
* @param {Object} [options]
- * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
+ * @param {Boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @param {Boolean} [options.new=false] By default, `findOneAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied.
@@ -3645,9 +3551,6 @@ Query.prototype._findOneAndReplace = async function _findOneAndReplace() {
convertNewToReturnDocument(options);
const includeResultMetadata = this.options.includeResultMetadata;
- if (this.options.rawResult && includeResultMetadata === false) {
- throw new MongooseError('Cannot set `rawResult` option when `includeResultMetadata` is false');
- }
const modelOpts = { skipId: true };
if ('strict' in this._mongooseOptions) {
@@ -3679,7 +3582,7 @@ Query.prototype._findOneAndReplace = async function _findOneAndReplace() {
res = fn(res);
}
- const doc = includeResultMetadata === false ? res : res.value;
+ const doc = !includeResultMetadata ? res : res.value;
return new Promise((resolve, reject) => {
this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => {
if (err) {
@@ -3711,19 +3614,6 @@ function convertNewToReturnDocument(options) {
}
}
-/**
- * Execute a `findOneAndRemove`. Alias for `findOneAndDelete`
- *
- * @return {Query} this
- * @method _findOneAndRemove
- * @memberOf Query
- * @instance
- * @api private
- */
-Query.prototype._findOneAndRemove = async function _findOneAndRemove() {
- return this._findOneAndDelete();
-};
-
/**
* Get options from query opts, falling back to the base mongoose object.
* @param {Query} query
@@ -3774,7 +3664,7 @@ function _completeOneLean(schema, doc, path, res, opts, callback) {
return;
}
}
- if (opts.rawResult) {
+ if (opts.includeResultMetadata) {
return callback(null, res);
}
return callback(null, doc);
@@ -4224,7 +4114,7 @@ function _update(query, op, filter, doc, options, callback) {
return query;
}
- return Query.base[op].call(query, filter, void 0, options, callback);
+ return query;
}
/**
@@ -4306,14 +4196,12 @@ Query.prototype.orFail = function(err) {
}
break;
case 'findOneAndDelete':
- case 'findOneAndRemove':
- if ((res && res.lastErrorObject && res.lastErrorObject.n) === 0) {
- throw _orFailError(err, this);
- }
- break;
case 'findOneAndUpdate':
case 'findOneAndReplace':
- if ((res && res.lastErrorObject && res.lastErrorObject.updatedExisting) === false) {
+ if (this.options.includeResultMetadata && res != null && res.value == null) {
+ throw _orFailError(err, this);
+ }
+ if (!this.options.includeResultMetadata && res == null) {
throw _orFailError(err, this);
}
break;
@@ -4420,14 +4308,23 @@ Query.prototype.exec = async function exec(op) {
this._executionStack = new Error();
}
- await _executePreExecHooks(this);
+ let skipWrappedFunction = null;
+ try {
+ await _executePreExecHooks(this);
+ } catch (err) {
+ if (err instanceof Kareem.skipWrappedFunction) {
+ skipWrappedFunction = err;
+ } else {
+ throw err;
+ }
+ }
let res;
let error = null;
try {
await _executePreHooks(this);
- res = await this[thunk]();
+ res = skipWrappedFunction ? skipWrappedFunction.args[0] : await this[thunk]();
for (const fn of this._transforms) {
res = fn(res);
@@ -5103,7 +5000,9 @@ Query.prototype.tailable = function(val, opts) {
}
}
- return Query.base.tailable.call(this, val);
+ this.options.tailable = arguments.length ? !!val : true;
+
+ return this;
};
/**
diff --git a/lib/queryhelpers.js b/lib/queryHelpers.js
similarity index 100%
rename from lib/queryhelpers.js
rename to lib/queryHelpers.js
diff --git a/lib/schema.js b/lib/schema.js
index 261211c1fb6..e0e0b03bf1d 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -7,10 +7,10 @@
const EventEmitter = require('events').EventEmitter;
const Kareem = require('kareem');
const MongooseError = require('./error/mongooseError');
-const SchemaType = require('./schematype');
+const SchemaType = require('./schemaType');
const SchemaTypeOptions = require('./options/SchemaTypeOptions');
const VirtualOptions = require('./options/VirtualOptions');
-const VirtualType = require('./virtualtype');
+const VirtualType = require('./virtualType');
const addAutoId = require('./helpers/schema/addAutoId');
const clone = require('./helpers/clone');
const get = require('./helpers/get');
diff --git a/lib/schema/DocumentArrayElement.js b/lib/schema/DocumentArrayElement.js
index a2fb9a44a23..5250b74b505 100644
--- a/lib/schema/DocumentArrayElement.js
+++ b/lib/schema/DocumentArrayElement.js
@@ -5,8 +5,8 @@
'use strict';
const MongooseError = require('../error/mongooseError');
-const SchemaType = require('../schematype');
-const SubdocumentPath = require('./SubdocumentPath');
+const SchemaType = require('../schemaType');
+const SchemaSubdocument = require('./subdocument');
const getConstructor = require('../helpers/discriminator/getConstructor');
/**
@@ -18,7 +18,7 @@ const getConstructor = require('../helpers/discriminator/getConstructor');
* @api public
*/
-function DocumentArrayElement(path, options) {
+function SchemaDocumentArrayElement(path, options) {
this.$parentSchemaType = options && options.$parentSchemaType;
if (!this.$parentSchemaType) {
throw new MongooseError('Cannot create DocumentArrayElement schematype without a parent');
@@ -36,15 +36,15 @@ function DocumentArrayElement(path, options) {
*
* @api public
*/
-DocumentArrayElement.schemaName = 'DocumentArrayElement';
+SchemaDocumentArrayElement.schemaName = 'DocumentArrayElement';
-DocumentArrayElement.defaultOptions = {};
+SchemaDocumentArrayElement.defaultOptions = {};
/*!
* Inherits from SchemaType.
*/
-DocumentArrayElement.prototype = Object.create(SchemaType.prototype);
-DocumentArrayElement.prototype.constructor = DocumentArrayElement;
+SchemaDocumentArrayElement.prototype = Object.create(SchemaType.prototype);
+SchemaDocumentArrayElement.prototype.constructor = SchemaDocumentArrayElement;
/**
* Casts `val` for DocumentArrayElement.
@@ -53,7 +53,7 @@ DocumentArrayElement.prototype.constructor = DocumentArrayElement;
* @api private
*/
-DocumentArrayElement.prototype.cast = function(...args) {
+SchemaDocumentArrayElement.prototype.cast = function(...args) {
return this.$parentSchemaType.cast(...args)[0];
};
@@ -65,14 +65,14 @@ DocumentArrayElement.prototype.cast = function(...args) {
* @api private
*/
-DocumentArrayElement.prototype.doValidate = function(value, fn, scope, options) {
+SchemaDocumentArrayElement.prototype.doValidate = function(value, fn, scope, options) {
const Constructor = getConstructor(this.caster, value);
if (value && !(value instanceof Constructor)) {
value = new Constructor(value, scope, null, null, options && options.index != null ? options.index : null);
}
- return SubdocumentPath.prototype.doValidate.call(this, value, fn, scope, options);
+ return SchemaSubdocument.prototype.doValidate.call(this, value, fn, scope, options);
};
/**
@@ -82,7 +82,7 @@ DocumentArrayElement.prototype.doValidate = function(value, fn, scope, options)
* @api private
*/
-DocumentArrayElement.prototype.clone = function() {
+SchemaDocumentArrayElement.prototype.clone = function() {
this.options.$parentSchemaType = this.$parentSchemaType;
const ret = SchemaType.prototype.clone.apply(this, arguments);
delete this.options.$parentSchemaType;
@@ -97,4 +97,4 @@ DocumentArrayElement.prototype.clone = function() {
* Module exports.
*/
-module.exports = DocumentArrayElement;
+module.exports = SchemaDocumentArrayElement;
diff --git a/lib/schema/array.js b/lib/schema/array.js
index 6d1c6de9628..f352d648589 100644
--- a/lib/schema/array.js
+++ b/lib/schema/array.js
@@ -8,7 +8,7 @@ const $exists = require('./operators/exists');
const $type = require('./operators/type');
const MongooseError = require('../error/mongooseError');
const SchemaArrayOptions = require('../options/SchemaArrayOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const CastError = SchemaType.CastError;
const Mixed = require('./mixed');
const arrayDepth = require('../helpers/arrayDepth');
diff --git a/lib/schema/bigint.js b/lib/schema/bigint.js
index 4c7dcb77039..c0c324fb370 100644
--- a/lib/schema/bigint.js
+++ b/lib/schema/bigint.js
@@ -5,7 +5,7 @@
*/
const CastError = require('../error/cast');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const castBigInt = require('../cast/bigint');
const utils = require('../utils');
diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js
index 316c825df45..d8da46a4c4f 100644
--- a/lib/schema/boolean.js
+++ b/lib/schema/boolean.js
@@ -5,7 +5,7 @@
*/
const CastError = require('../error/cast');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const castBoolean = require('../cast/boolean');
const utils = require('../utils');
diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index 5bfaabcd2f6..9e4586ffa3a 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -6,7 +6,7 @@
const MongooseBuffer = require('../types/buffer');
const SchemaBufferOptions = require('../options/SchemaBufferOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const handleBitwiseOperator = require('./operators/bitwise');
const utils = require('../utils');
diff --git a/lib/schema/date.js b/lib/schema/date.js
index 61928bb457d..1d2f871e263 100644
--- a/lib/schema/date.js
+++ b/lib/schema/date.js
@@ -6,7 +6,7 @@
const MongooseError = require('../error/index');
const SchemaDateOptions = require('../options/SchemaDateOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const castDate = require('../cast/date');
const getConstructorName = require('../helpers/getConstructorName');
const utils = require('../utils');
diff --git a/lib/schema/decimal128.js b/lib/schema/decimal128.js
index 650d78c2571..356bf52c3ba 100644
--- a/lib/schema/decimal128.js
+++ b/lib/schema/decimal128.js
@@ -4,7 +4,7 @@
'use strict';
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const CastError = SchemaType.CastError;
const castDecimal128 = require('../cast/decimal128');
const utils = require('../utils');
@@ -19,7 +19,7 @@ const isBsonType = require('../helpers/isBsonType');
* @api public
*/
-function Decimal128(key, options) {
+function SchemaDecimal128(key, options) {
SchemaType.call(this, key, options, 'Decimal128');
}
@@ -29,21 +29,21 @@ function Decimal128(key, options) {
*
* @api public
*/
-Decimal128.schemaName = 'Decimal128';
+SchemaDecimal128.schemaName = 'Decimal128';
-Decimal128.defaultOptions = {};
+SchemaDecimal128.defaultOptions = {};
/*!
* Inherits from SchemaType.
*/
-Decimal128.prototype = Object.create(SchemaType.prototype);
-Decimal128.prototype.constructor = Decimal128;
+SchemaDecimal128.prototype = Object.create(SchemaType.prototype);
+SchemaDecimal128.prototype.constructor = SchemaDecimal128;
/*!
* ignore
*/
-Decimal128._cast = castDecimal128;
+SchemaDecimal128._cast = castDecimal128;
/**
* Sets a default option for all Decimal128 instances.
@@ -64,9 +64,9 @@ Decimal128._cast = castDecimal128;
* @api public
*/
-Decimal128.set = SchemaType.set;
+SchemaDecimal128.set = SchemaType.set;
-Decimal128.setters = [];
+SchemaDecimal128.setters = [];
/**
* Attaches a getter for all Decimal128 instances
@@ -83,7 +83,7 @@ Decimal128.setters = [];
* @api public
*/
-Decimal128.get = SchemaType.get;
+SchemaDecimal128.get = SchemaType.get;
/**
* Get/set the function used to cast arbitrary values to decimals.
@@ -107,7 +107,7 @@ Decimal128.get = SchemaType.get;
* @api public
*/
-Decimal128.cast = function cast(caster) {
+SchemaDecimal128.cast = function cast(caster) {
if (arguments.length === 0) {
return this._cast;
}
@@ -123,7 +123,7 @@ Decimal128.cast = function cast(caster) {
* ignore
*/
-Decimal128._defaultCaster = v => {
+SchemaDecimal128._defaultCaster = v => {
if (v != null && !isBsonType(v, 'Decimal128')) {
throw new Error();
}
@@ -134,7 +134,7 @@ Decimal128._defaultCaster = v => {
* ignore
*/
-Decimal128._checkRequired = v => isBsonType(v, 'Decimal128');
+SchemaDecimal128._checkRequired = v => isBsonType(v, 'Decimal128');
/**
* Override the function the required validator uses to check whether a string
@@ -147,7 +147,7 @@ Decimal128._checkRequired = v => isBsonType(v, 'Decimal128');
* @api public
*/
-Decimal128.checkRequired = SchemaType.checkRequired;
+SchemaDecimal128.checkRequired = SchemaType.checkRequired;
/**
* Check if the given value satisfies a required validator.
@@ -158,7 +158,7 @@ Decimal128.checkRequired = SchemaType.checkRequired;
* @api public
*/
-Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
+SchemaDecimal128.prototype.checkRequired = function checkRequired(value, doc) {
if (SchemaType._isRef(this, value, doc, true)) {
return !!value;
}
@@ -167,7 +167,7 @@ Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
// plugins like mongoose-float use `inherits()` for pre-ES6.
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
this.constructor.checkRequired() :
- Decimal128.checkRequired();
+ SchemaDecimal128.checkRequired();
return _checkRequired(value);
};
@@ -181,7 +181,7 @@ Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
* @api private
*/
-Decimal128.prototype.cast = function(value, doc, init) {
+SchemaDecimal128.prototype.cast = function(value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
if (isBsonType(value, 'Decimal128')) {
return value;
@@ -196,7 +196,7 @@ Decimal128.prototype.cast = function(value, doc, init) {
} else if (typeof this.constructor.cast === 'function') {
castDecimal128 = this.constructor.cast();
} else {
- castDecimal128 = Decimal128.cast();
+ castDecimal128 = SchemaDecimal128.cast();
}
try {
@@ -214,7 +214,7 @@ function handleSingle(val) {
return this.cast(val);
}
-Decimal128.prototype.$conditionalHandlers =
+SchemaDecimal128.prototype.$conditionalHandlers =
utils.options(SchemaType.prototype.$conditionalHandlers, {
$gt: handleSingle,
$gte: handleSingle,
@@ -226,4 +226,4 @@ Decimal128.prototype.$conditionalHandlers =
* Module exports.
*/
-module.exports = Decimal128;
+module.exports = SchemaDecimal128;
diff --git a/lib/schema/documentarray.js b/lib/schema/documentArray.js
similarity index 91%
rename from lib/schema/documentarray.js
rename to lib/schema/documentArray.js
index 7f8a39a04d6..443e3caa13c 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentArray.js
@@ -4,13 +4,13 @@
* Module dependencies.
*/
-const ArrayType = require('./array');
const CastError = require('../error/cast');
const DocumentArrayElement = require('./DocumentArrayElement');
const EventEmitter = require('events').EventEmitter;
+const SchemaArray = require('./array');
const SchemaDocumentArrayOptions =
require('../options/SchemaDocumentArrayOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const discriminator = require('../helpers/model/discriminator');
const handleIdOption = require('../helpers/schema/handleIdOption');
const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
@@ -36,12 +36,12 @@ let Subdocument;
* @api public
*/
-function DocumentArrayPath(key, schema, options, schemaOptions) {
+function SchemaDocumentArray(key, schema, options, schemaOptions) {
if (schema.options && schema.options.timeseries) {
throw new InvalidSchemaOptionError(key, 'timeseries');
}
- const schemaTypeIdOption = DocumentArrayPath.defaultOptions &&
- DocumentArrayPath.defaultOptions._id;
+ const schemaTypeIdOption = SchemaDocumentArray.defaultOptions &&
+ SchemaDocumentArray.defaultOptions._id;
if (schemaTypeIdOption != null) {
schemaOptions = schemaOptions || {};
schemaOptions._id = schemaTypeIdOption;
@@ -56,7 +56,7 @@ function DocumentArrayPath(key, schema, options, schemaOptions) {
const EmbeddedDocument = _createConstructor(schema, options);
EmbeddedDocument.prototype.$basePath = key;
- ArrayType.call(this, key, EmbeddedDocument, options);
+ SchemaArray.call(this, key, EmbeddedDocument, options);
this.schema = schema;
this.schemaOptions = schemaOptions || {};
@@ -96,7 +96,7 @@ function DocumentArrayPath(key, schema, options, schemaOptions) {
*
* @api public
*/
-DocumentArrayPath.schemaName = 'DocumentArray';
+SchemaDocumentArray.schemaName = 'DocumentArray';
/**
* Options for all document arrays.
@@ -106,14 +106,14 @@ DocumentArrayPath.schemaName = 'DocumentArray';
* @api public
*/
-DocumentArrayPath.options = { castNonArrays: true };
+SchemaDocumentArray.options = { castNonArrays: true };
/*!
- * Inherits from ArrayType.
+ * Inherits from SchemaArray.
*/
-DocumentArrayPath.prototype = Object.create(ArrayType.prototype);
-DocumentArrayPath.prototype.constructor = DocumentArrayPath;
-DocumentArrayPath.prototype.OptionsConstructor = SchemaDocumentArrayOptions;
+SchemaDocumentArray.prototype = Object.create(SchemaArray.prototype);
+SchemaDocumentArray.prototype.constructor = SchemaDocumentArray;
+SchemaDocumentArray.prototype.OptionsConstructor = SchemaDocumentArrayOptions;
/*!
* ignore
@@ -182,7 +182,7 @@ function _createConstructor(schema, options, baseClass) {
* @api public
*/
-DocumentArrayPath.prototype.discriminator = function(name, schema, options) {
+SchemaDocumentArray.prototype.discriminator = function(name, schema, options) {
if (typeof name === 'function') {
name = utils.getFunctionName(name);
}
@@ -219,7 +219,7 @@ DocumentArrayPath.prototype.discriminator = function(name, schema, options) {
* @api private
*/
-DocumentArrayPath.prototype.doValidate = function(array, fn, scope, options) {
+SchemaDocumentArray.prototype.doValidate = function(array, fn, scope, options) {
// lazy load
MongooseDocumentArray || (MongooseDocumentArray = require('../types/DocumentArray'));
@@ -295,7 +295,7 @@ DocumentArrayPath.prototype.doValidate = function(array, fn, scope, options) {
* @api private
*/
-DocumentArrayPath.prototype.doValidateSync = function(array, scope, options) {
+SchemaDocumentArray.prototype.doValidateSync = function(array, scope, options) {
const schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope);
if (schemaTypeError != null) {
return schemaTypeError;
@@ -344,7 +344,7 @@ DocumentArrayPath.prototype.doValidateSync = function(array, scope, options) {
* ignore
*/
-DocumentArrayPath.prototype.getDefault = function(scope, init, options) {
+SchemaDocumentArray.prototype.getDefault = function(scope, init, options) {
let ret = typeof this.defaultValue === 'function'
? this.defaultValue.call(scope)
: this.defaultValue;
@@ -395,7 +395,7 @@ const initDocumentOptions = Object.freeze({ skipId: false, willInit: true });
* @api private
*/
-DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
+SchemaDocumentArray.prototype.cast = function(value, doc, init, prev, options) {
// lazy load
MongooseDocumentArray || (MongooseDocumentArray = require('../types/DocumentArray'));
@@ -412,7 +412,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
const path = options.path || this.path;
if (!Array.isArray(value)) {
- if (!init && !DocumentArrayPath.options.castNonArrays) {
+ if (!init && !SchemaDocumentArray.options.castNonArrays) {
throw new CastError('DocumentArray', value, this.path, null, this);
}
// gh-2442 mark whole array as modified if we're initializing a doc from
@@ -520,7 +520,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
* ignore
*/
-DocumentArrayPath.prototype.clone = function() {
+SchemaDocumentArray.prototype.clone = function() {
const options = Object.assign({}, this.options);
const schematype = new this.constructor(this.path, this.schema, options, this.schemaOptions);
schematype.validators = this.validators.slice();
@@ -536,7 +536,7 @@ DocumentArrayPath.prototype.clone = function() {
* ignore
*/
-DocumentArrayPath.prototype.applyGetters = function(value, scope) {
+SchemaDocumentArray.prototype.applyGetters = function(value, scope) {
return SchemaType.prototype.applyGetters.call(this, value, scope);
};
@@ -585,7 +585,7 @@ function scopePaths(array, fields, init) {
* ignore
*/
-DocumentArrayPath.defaultOptions = {};
+SchemaDocumentArray.defaultOptions = {};
/**
* Sets a default option for all DocumentArray instances.
@@ -603,9 +603,9 @@ DocumentArrayPath.defaultOptions = {};
* @api public
*/
-DocumentArrayPath.set = SchemaType.set;
+SchemaDocumentArray.set = SchemaType.set;
-DocumentArrayPath.setters = [];
+SchemaDocumentArray.setters = [];
/**
* Attaches a getter for all DocumentArrayPath instances
@@ -617,10 +617,10 @@ DocumentArrayPath.setters = [];
* @api public
*/
-DocumentArrayPath.get = SchemaType.get;
+SchemaDocumentArray.get = SchemaType.get;
/*!
* Module exports.
*/
-module.exports = DocumentArrayPath;
+module.exports = SchemaDocumentArray;
diff --git a/lib/schema/index.js b/lib/schema/index.js
index 4bd4d8d5934..0caf091adf2 100644
--- a/lib/schema/index.js
+++ b/lib/schema/index.js
@@ -6,18 +6,18 @@
'use strict';
exports.Array = require('./array');
-exports.Boolean = require('./boolean');
exports.BigInt = require('./bigint');
+exports.Boolean = require('./boolean');
exports.Buffer = require('./buffer');
exports.Date = require('./date');
exports.Decimal128 = exports.Decimal = require('./decimal128');
-exports.DocumentArray = require('./documentarray');
+exports.DocumentArray = require('./documentArray');
exports.Map = require('./map');
exports.Mixed = require('./mixed');
exports.Number = require('./number');
-exports.ObjectId = require('./objectid');
+exports.ObjectId = require('./objectId');
exports.String = require('./string');
-exports.Subdocument = require('./SubdocumentPath');
+exports.Subdocument = require('./subdocument');
exports.UUID = require('./uuid');
// alias
diff --git a/lib/schema/map.js b/lib/schema/map.js
index ce25a11f568..89ecc6a1cd0 100644
--- a/lib/schema/map.js
+++ b/lib/schema/map.js
@@ -6,12 +6,12 @@
const MongooseMap = require('../types/map');
const SchemaMapOptions = require('../options/SchemaMapOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
/*!
* ignore
*/
-class Map extends SchemaType {
+class SchemaMap extends SchemaType {
constructor(key, options) {
super(key, options, 'Map');
this.$isSchemaMap = true;
@@ -75,10 +75,10 @@ class Map extends SchemaType {
*
* @api public
*/
-Map.schemaName = 'Map';
+SchemaMap.schemaName = 'Map';
-Map.prototype.OptionsConstructor = SchemaMapOptions;
+SchemaMap.prototype.OptionsConstructor = SchemaMapOptions;
-Map.defaultOptions = {};
+SchemaMap.defaultOptions = {};
-module.exports = Map;
+module.exports = SchemaMap;
diff --git a/lib/schema/mixed.js b/lib/schema/mixed.js
index bd38a286213..a645a981f7b 100644
--- a/lib/schema/mixed.js
+++ b/lib/schema/mixed.js
@@ -4,7 +4,7 @@
'use strict';
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const symbols = require('./symbols');
const isObject = require('../helpers/isObject');
const utils = require('../utils');
@@ -18,7 +18,7 @@ const utils = require('../utils');
* @api public
*/
-function Mixed(path, options) {
+function SchemaMixed(path, options) {
if (options && options.default) {
const def = options.default;
if (Array.isArray(def) && def.length === 0) {
@@ -43,15 +43,15 @@ function Mixed(path, options) {
*
* @api public
*/
-Mixed.schemaName = 'Mixed';
+SchemaMixed.schemaName = 'Mixed';
-Mixed.defaultOptions = {};
+SchemaMixed.defaultOptions = {};
/*!
* Inherits from SchemaType.
*/
-Mixed.prototype = Object.create(SchemaType.prototype);
-Mixed.prototype.constructor = Mixed;
+SchemaMixed.prototype = Object.create(SchemaType.prototype);
+SchemaMixed.prototype.constructor = SchemaMixed;
/**
* Attaches a getter for all Mixed paths.
@@ -71,7 +71,7 @@ Mixed.prototype.constructor = Mixed;
* @api public
*/
-Mixed.get = SchemaType.get;
+SchemaMixed.get = SchemaType.get;
/**
* Sets a default option for all Mixed instances.
@@ -92,9 +92,9 @@ Mixed.get = SchemaType.get;
* @api public
*/
-Mixed.set = SchemaType.set;
+SchemaMixed.set = SchemaType.set;
-Mixed.setters = [];
+SchemaMixed.setters = [];
/**
* Casts `val` for Mixed.
@@ -105,7 +105,7 @@ Mixed.setters = [];
* @api private
*/
-Mixed.prototype.cast = function(val) {
+SchemaMixed.prototype.cast = function(val) {
if (val instanceof Error) {
return utils.errorToPOJO(val);
}
@@ -120,7 +120,7 @@ Mixed.prototype.cast = function(val) {
* @api private
*/
-Mixed.prototype.castForQuery = function($cond, val) {
+SchemaMixed.prototype.castForQuery = function($cond, val) {
return val;
};
@@ -128,4 +128,4 @@ Mixed.prototype.castForQuery = function($cond, val) {
* Module exports.
*/
-module.exports = Mixed;
+module.exports = SchemaMixed;
diff --git a/lib/schema/number.js b/lib/schema/number.js
index b2695cd94a6..8400cfb1bf6 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -6,7 +6,7 @@
const MongooseError = require('../error/index');
const SchemaNumberOptions = require('../options/SchemaNumberOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const castNumber = require('../cast/number');
const handleBitwiseOperator = require('./operators/bitwise');
const utils = require('../utils');
diff --git a/lib/schema/objectid.js b/lib/schema/objectId.js
similarity index 84%
rename from lib/schema/objectid.js
rename to lib/schema/objectId.js
index f0a0b6be747..d1d502bfa03 100644
--- a/lib/schema/objectid.js
+++ b/lib/schema/objectId.js
@@ -5,7 +5,7 @@
'use strict';
const SchemaObjectIdOptions = require('../options/SchemaObjectIdOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const castObjectId = require('../cast/objectid');
const getConstructorName = require('../helpers/getConstructorName');
const oid = require('../types/objectid');
@@ -24,7 +24,7 @@ let Document;
* @api public
*/
-function ObjectId(key, options) {
+function SchemaObjectId(key, options) {
const isKeyHexStr = typeof key === 'string' && key.length === 24 && /^[a-f0-9]+$/i.test(key);
const suppressWarning = options && options.suppressWarning;
if ((isKeyHexStr || typeof key === 'undefined') && !suppressWarning) {
@@ -42,16 +42,16 @@ function ObjectId(key, options) {
*
* @api public
*/
-ObjectId.schemaName = 'ObjectId';
+SchemaObjectId.schemaName = 'ObjectId';
-ObjectId.defaultOptions = {};
+SchemaObjectId.defaultOptions = {};
/*!
* Inherits from SchemaType.
*/
-ObjectId.prototype = Object.create(SchemaType.prototype);
-ObjectId.prototype.constructor = ObjectId;
-ObjectId.prototype.OptionsConstructor = SchemaObjectIdOptions;
+SchemaObjectId.prototype = Object.create(SchemaType.prototype);
+SchemaObjectId.prototype.constructor = SchemaObjectId;
+SchemaObjectId.prototype.OptionsConstructor = SchemaObjectIdOptions;
/**
* Attaches a getter for all ObjectId instances
@@ -71,7 +71,7 @@ ObjectId.prototype.OptionsConstructor = SchemaObjectIdOptions;
* @api public
*/
-ObjectId.get = SchemaType.get;
+SchemaObjectId.get = SchemaType.get;
/**
* Sets a default option for all ObjectId instances.
@@ -92,9 +92,9 @@ ObjectId.get = SchemaType.get;
* @api public
*/
-ObjectId.set = SchemaType.set;
+SchemaObjectId.set = SchemaType.set;
-ObjectId.setters = [];
+SchemaObjectId.setters = [];
/**
* Adds an auto-generated ObjectId default if turnOn is true.
@@ -103,7 +103,7 @@ ObjectId.setters = [];
* @return {SchemaType} this
*/
-ObjectId.prototype.auto = function(turnOn) {
+SchemaObjectId.prototype.auto = function(turnOn) {
if (turnOn) {
this.default(defaultId);
this.set(resetId);
@@ -116,13 +116,13 @@ ObjectId.prototype.auto = function(turnOn) {
* ignore
*/
-ObjectId._checkRequired = v => isBsonType(v, 'ObjectId');
+SchemaObjectId._checkRequired = v => isBsonType(v, 'ObjectId');
/*!
* ignore
*/
-ObjectId._cast = castObjectId;
+SchemaObjectId._cast = castObjectId;
/**
* Get/set the function used to cast arbitrary values to objectids.
@@ -147,7 +147,7 @@ ObjectId._cast = castObjectId;
* @api public
*/
-ObjectId.cast = function cast(caster) {
+SchemaObjectId.cast = function cast(caster) {
if (arguments.length === 0) {
return this._cast;
}
@@ -163,7 +163,7 @@ ObjectId.cast = function cast(caster) {
* ignore
*/
-ObjectId._defaultCaster = v => {
+SchemaObjectId._defaultCaster = v => {
if (!(isBsonType(v, 'ObjectId'))) {
throw new Error(v + ' is not an instance of ObjectId');
}
@@ -189,7 +189,7 @@ ObjectId._defaultCaster = v => {
* @api public
*/
-ObjectId.checkRequired = SchemaType.checkRequired;
+SchemaObjectId.checkRequired = SchemaType.checkRequired;
/**
* Check if the given value satisfies a required validator.
@@ -200,7 +200,7 @@ ObjectId.checkRequired = SchemaType.checkRequired;
* @api public
*/
-ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
+SchemaObjectId.prototype.checkRequired = function checkRequired(value, doc) {
if (SchemaType._isRef(this, value, doc, true)) {
return !!value;
}
@@ -209,7 +209,7 @@ ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
// plugins like mongoose-float use `inherits()` for pre-ES6.
const _checkRequired = typeof this.constructor.checkRequired === 'function' ?
this.constructor.checkRequired() :
- ObjectId.checkRequired();
+ SchemaObjectId.checkRequired();
return _checkRequired(value);
};
@@ -223,7 +223,7 @@ ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
* @api private
*/
-ObjectId.prototype.cast = function(value, doc, init) {
+SchemaObjectId.prototype.cast = function(value, doc, init) {
if (!(isBsonType(value, 'ObjectId')) && SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document
if ((getConstructorName(value) || '').toLowerCase() === 'objectid') {
@@ -241,7 +241,7 @@ ObjectId.prototype.cast = function(value, doc, init) {
} else if (typeof this.constructor.cast === 'function') {
castObjectId = this.constructor.cast();
} else {
- castObjectId = ObjectId.cast();
+ castObjectId = SchemaObjectId.cast();
}
try {
@@ -259,7 +259,7 @@ function handleSingle(val) {
return this.cast(val);
}
-ObjectId.prototype.$conditionalHandlers =
+SchemaObjectId.prototype.$conditionalHandlers =
utils.options(SchemaType.prototype.$conditionalHandlers, {
$gt: handleSingle,
$gte: handleSingle,
@@ -278,7 +278,7 @@ function defaultId() {
defaultId.$runBeforeSetters = true;
function resetId(v) {
- Document || (Document = require('./../document'));
+ Document || (Document = require('../document'));
if (this instanceof Document) {
if (v === void 0) {
@@ -294,4 +294,4 @@ function resetId(v) {
* Module exports.
*/
-module.exports = ObjectId;
+module.exports = SchemaObjectId;
diff --git a/lib/schema/string.js b/lib/schema/string.js
index 5caee2e3cfc..07a08a14ba0 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -4,7 +4,7 @@
* Module dependencies.
*/
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const MongooseError = require('../error/index');
const SchemaStringOptions = require('../options/SchemaStringOptions');
const castString = require('../cast/string');
@@ -244,7 +244,7 @@ SchemaString.prototype.enum = function() {
const vals = this.enumValues;
this.enumValidator = function(v) {
- return undefined === v || ~vals.indexOf(v);
+ return null == v || ~vals.indexOf(v);
};
this.validators.push({
validator: this.enumValidator,
diff --git a/lib/schema/SubdocumentPath.js b/lib/schema/subdocument.js
similarity index 80%
rename from lib/schema/SubdocumentPath.js
rename to lib/schema/subdocument.js
index 5d4cc6db041..7a837427f31 100644
--- a/lib/schema/SubdocumentPath.js
+++ b/lib/schema/subdocument.js
@@ -8,7 +8,7 @@ const CastError = require('../error/cast');
const EventEmitter = require('events').EventEmitter;
const ObjectExpectedError = require('../error/objectExpected');
const SchemaSubdocumentOptions = require('../options/SchemaSubdocumentOptions');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const applyDefaults = require('../helpers/document/applyDefaults');
const $exists = require('./operators/exists');
const castToNumber = require('./operators/helpers').castToNumber;
@@ -21,9 +21,9 @@ const isExclusive = require('../helpers/projection/isExclusive');
const utils = require('../utils');
const InvalidSchemaOptionError = require('../error/invalidSchemaOption');
-let Subdocument;
+let SubdocumentType;
-module.exports = SubdocumentPath;
+module.exports = SchemaSubdocument;
/**
* Single nested subdocument SchemaType constructor.
@@ -35,12 +35,12 @@ module.exports = SubdocumentPath;
* @api public
*/
-function SubdocumentPath(schema, path, options) {
+function SchemaSubdocument(schema, path, options) {
if (schema.options.timeseries) {
throw new InvalidSchemaOptionError(path, 'timeseries');
}
- const schemaTypeIdOption = SubdocumentPath.defaultOptions &&
- SubdocumentPath.defaultOptions._id;
+ const schemaTypeIdOption = SchemaSubdocument.defaultOptions &&
+ SchemaSubdocument.defaultOptions._id;
if (schemaTypeIdOption != null) {
options = options || {};
options._id = schemaTypeIdOption;
@@ -61,9 +61,9 @@ function SubdocumentPath(schema, path, options) {
* ignore
*/
-SubdocumentPath.prototype = Object.create(SchemaType.prototype);
-SubdocumentPath.prototype.constructor = SubdocumentPath;
-SubdocumentPath.prototype.OptionsConstructor = SchemaSubdocumentOptions;
+SchemaSubdocument.prototype = Object.create(SchemaType.prototype);
+SchemaSubdocument.prototype.constructor = SchemaSubdocument;
+SchemaSubdocument.prototype.OptionsConstructor = SchemaSubdocumentOptions;
/*!
* ignore
@@ -71,11 +71,11 @@ SubdocumentPath.prototype.OptionsConstructor = SchemaSubdocumentOptions;
function _createConstructor(schema, baseClass) {
// lazy load
- Subdocument || (Subdocument = require('../types/subdocument'));
+ SubdocumentType || (SubdocumentType = require('../types/subdocument'));
const _embedded = function SingleNested(value, path, parent) {
this.$__parent = parent;
- Subdocument.apply(this, arguments);
+ SubdocumentType.apply(this, arguments);
if (parent == null) {
return;
@@ -85,7 +85,7 @@ function _createConstructor(schema, baseClass) {
schema._preCompile();
- const proto = baseClass != null ? baseClass.prototype : Subdocument.prototype;
+ const proto = baseClass != null ? baseClass.prototype : SubdocumentType.prototype;
_embedded.prototype = Object.create(proto);
_embedded.prototype.$__setSchema(schema);
_embedded.prototype.constructor = _embedded;
@@ -123,7 +123,7 @@ function _createConstructor(schema, baseClass) {
* @api private
*/
-SubdocumentPath.prototype.$conditionalHandlers.$geoWithin = function handle$geoWithin(val, context) {
+SchemaSubdocument.prototype.$conditionalHandlers.$geoWithin = function handle$geoWithin(val, context) {
return { $geometry: this.castForQuery(null, val.$geometry, context) };
};
@@ -131,19 +131,19 @@ SubdocumentPath.prototype.$conditionalHandlers.$geoWithin = function handle$geoW
* ignore
*/
-SubdocumentPath.prototype.$conditionalHandlers.$near =
-SubdocumentPath.prototype.$conditionalHandlers.$nearSphere = geospatial.cast$near;
+SchemaSubdocument.prototype.$conditionalHandlers.$near =
+SchemaSubdocument.prototype.$conditionalHandlers.$nearSphere = geospatial.cast$near;
-SubdocumentPath.prototype.$conditionalHandlers.$within =
-SubdocumentPath.prototype.$conditionalHandlers.$geoWithin = geospatial.cast$within;
+SchemaSubdocument.prototype.$conditionalHandlers.$within =
+SchemaSubdocument.prototype.$conditionalHandlers.$geoWithin = geospatial.cast$within;
-SubdocumentPath.prototype.$conditionalHandlers.$geoIntersects =
+SchemaSubdocument.prototype.$conditionalHandlers.$geoIntersects =
geospatial.cast$geoIntersects;
-SubdocumentPath.prototype.$conditionalHandlers.$minDistance = castToNumber;
-SubdocumentPath.prototype.$conditionalHandlers.$maxDistance = castToNumber;
+SchemaSubdocument.prototype.$conditionalHandlers.$minDistance = castToNumber;
+SchemaSubdocument.prototype.$conditionalHandlers.$maxDistance = castToNumber;
-SubdocumentPath.prototype.$conditionalHandlers.$exists = $exists;
+SchemaSubdocument.prototype.$conditionalHandlers.$exists = $exists;
/**
* Casts contents
@@ -152,7 +152,7 @@ SubdocumentPath.prototype.$conditionalHandlers.$exists = $exists;
* @api private
*/
-SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) {
+SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
if (val && val.$isSingleNested && val.parent === doc) {
return val;
}
@@ -201,7 +201,7 @@ SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) {
* @api private
*/
-SubdocumentPath.prototype.castForQuery = function($conditional, val, context, options) {
+SchemaSubdocument.prototype.castForQuery = function($conditional, val, context, options) {
let handler;
if ($conditional != null) {
handler = this.$conditionalHandlers[$conditional];
@@ -245,7 +245,7 @@ SubdocumentPath.prototype.castForQuery = function($conditional, val, context, op
* @api private
*/
-SubdocumentPath.prototype.doValidate = function(value, fn, scope, options) {
+SchemaSubdocument.prototype.doValidate = function(value, fn, scope, options) {
const Constructor = getConstructor(this.caster, value);
if (value && !(value instanceof Constructor)) {
@@ -277,7 +277,7 @@ SubdocumentPath.prototype.doValidate = function(value, fn, scope, options) {
* @api private
*/
-SubdocumentPath.prototype.doValidateSync = function(value, scope, options) {
+SchemaSubdocument.prototype.doValidateSync = function(value, scope, options) {
if (!options || !options.skipSchemaValidators) {
const schemaTypeError = SchemaType.prototype.doValidateSync.call(this, value, scope);
if (schemaTypeError) {
@@ -311,7 +311,7 @@ SubdocumentPath.prototype.doValidateSync = function(value, scope, options) {
* @api public
*/
-SubdocumentPath.prototype.discriminator = function(name, schema, options) {
+SchemaSubdocument.prototype.discriminator = function(name, schema, options) {
options = options || {};
const value = utils.isPOJO(options) ? options.value : options;
const clone = typeof options.clone === 'boolean'
@@ -333,15 +333,15 @@ SubdocumentPath.prototype.discriminator = function(name, schema, options) {
* ignore
*/
-SubdocumentPath.defaultOptions = {};
+SchemaSubdocument.defaultOptions = {};
/**
- * Sets a default option for all SubdocumentPath instances.
+ * Sets a default option for all Subdocument instances.
*
* #### Example:
*
* // Make all numbers have option `min` equal to 0.
- * mongoose.Schema.SubdocumentPath.set('required', true);
+ * mongoose.Schema.Subdocument.set('required', true);
*
* @param {String} option The option you'd like to set the value for
* @param {Any} value value for option
@@ -351,12 +351,12 @@ SubdocumentPath.defaultOptions = {};
* @api public
*/
-SubdocumentPath.set = SchemaType.set;
+SchemaSubdocument.set = SchemaType.set;
-SubdocumentPath.setters = [];
+SchemaSubdocument.setters = [];
/**
- * Attaches a getter for all SubdocumentPath instances
+ * Attaches a getter for all Subdocument instances
*
* @param {Function} getter
* @return {this}
@@ -365,13 +365,13 @@ SubdocumentPath.setters = [];
* @api public
*/
-SubdocumentPath.get = SchemaType.get;
+SchemaSubdocument.get = SchemaType.get;
/*!
* ignore
*/
-SubdocumentPath.prototype.toJSON = function toJSON() {
+SchemaSubdocument.prototype.toJSON = function toJSON() {
return { path: this.path, options: this.options };
};
@@ -379,7 +379,7 @@ SubdocumentPath.prototype.toJSON = function toJSON() {
* ignore
*/
-SubdocumentPath.prototype.clone = function() {
+SchemaSubdocument.prototype.clone = function() {
const options = Object.assign({}, this.options);
const schematype = new this.constructor(this.schema, this.path, options);
schematype.validators = this.validators.slice();
diff --git a/lib/schema/uuid.js b/lib/schema/uuid.js
index 9de95f6cd4d..62a9baac55b 100644
--- a/lib/schema/uuid.js
+++ b/lib/schema/uuid.js
@@ -5,7 +5,7 @@
'use strict';
const MongooseBuffer = require('../types/buffer');
-const SchemaType = require('../schematype');
+const SchemaType = require('../schemaType');
const CastError = SchemaType.CastError;
const utils = require('../utils');
const handleBitwiseOperator = require('./operators/bitwise');
diff --git a/lib/schematype.js b/lib/schemaType.js
similarity index 100%
rename from lib/schematype.js
rename to lib/schemaType.js
diff --git a/lib/statemachine.js b/lib/stateMachine.js
similarity index 100%
rename from lib/statemachine.js
rename to lib/stateMachine.js
diff --git a/lib/validoptions.js b/lib/validOptions.js
similarity index 100%
rename from lib/validoptions.js
rename to lib/validOptions.js
diff --git a/lib/virtualtype.js b/lib/virtualType.js
similarity index 100%
rename from lib/virtualtype.js
rename to lib/virtualType.js
diff --git a/package.json b/package.json
index b2d00055e50..49ba8faafda 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "mongoose",
"description": "Mongoose MongoDB ODM",
- "version": "7.5.0",
+ "version": "7.5.1",
"author": "Guillermo Rauch ",
"keywords": [
"mongodb",
@@ -19,9 +19,9 @@
],
"license": "MIT",
"dependencies": {
- "bson": "^5.4.0",
+ "bson": "^6.0.0",
"kareem": "2.5.1",
- "mongodb": "5.8.1",
+ "mongodb": "6.0.0",
"mpath": "0.9.0",
"mquery": "5.0.0",
"ms": "2.1.3",
@@ -30,8 +30,8 @@
"devDependencies": {
"@babel/core": "7.22.11",
"@babel/preset-env": "7.22.14",
- "@typescript-eslint/eslint-plugin": "5.61.0",
- "@typescript-eslint/parser": "5.62.0",
+ "@typescript-eslint/eslint-plugin": "^6.2.1",
+ "@typescript-eslint/parser": "^6.2.1",
"acquit": "1.3.0",
"acquit-ignore": "0.2.1",
"acquit-require": "0.1.1",
@@ -47,7 +47,7 @@
"dotenv": "16.3.1",
"dox": "1.0.0",
"eslint": "8.48.0",
- "eslint-plugin-markdown": "^3.0.0",
+ "eslint-plugin-markdown": "^3.0.1",
"eslint-plugin-mocha-no-only": "1.1.1",
"express": "^4.18.1",
"fs-extra": "~11.1.1",
@@ -119,7 +119,7 @@
"main": "./index.js",
"types": "./types/index.d.ts",
"engines": {
- "node": ">=14.20.1"
+ "node": ">=16.20.1"
},
"bugs": {
"url": "https://github.com/Automattic/mongoose/issues/new"
diff --git a/test/connection.test.js b/test/connection.test.js
index 30b5f640f81..f84aaa9dd82 100644
--- a/test/connection.test.js
+++ b/test/connection.test.js
@@ -6,7 +6,7 @@
const start = require('./common');
-const STATES = require('../lib/connectionstate');
+const STATES = require('../lib/connectionState');
const Q = require('q');
const assert = require('assert');
const mongodb = require('mongodb');
diff --git a/test/docs/findoneandupdate.test.js b/test/docs/findoneandupdate.test.js
index e6cbaf8fe96..2fde28cd688 100644
--- a/test/docs/findoneandupdate.test.js
+++ b/test/docs/findoneandupdate.test.js
@@ -139,7 +139,7 @@ describe('Tutorial: findOneAndUpdate()', function() {
// acquit:ignore:end
});
- it('rawResult', async function() {
+ it('includeResultMetadata', async function() {
const filter = { name: 'Will Riker' };
const update = { age: 29 };
@@ -151,7 +151,8 @@ describe('Tutorial: findOneAndUpdate()', function() {
const res = await Character.findOneAndUpdate(filter, update, {
new: true,
upsert: true,
- rawResult: true // Return the raw result from the MongoDB driver
+ // Return additional properties about the operation, not just the document
+ includeResultMetadata: true
});
res.value instanceof Character; // true
diff --git a/test/document.test.js b/test/document.test.js
index 470ca60f8c5..6f41e2f2c9f 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -153,10 +153,11 @@ describe('document', function() {
const test = new Test({ x: 'test' });
const doc = await test.save();
- await doc.deleteOne();
+ const q = doc.deleteOne();
+ assert.ok(q instanceof mongoose.Query, `Expected query, got ${q.constructor.name}`);
+ await q;
const found = await Test.findOne({ _id: doc._id });
assert.strictEqual(found, null);
-
});
});
@@ -1944,7 +1945,7 @@ describe('document', function() {
const Person = db.model('Person', personSchema);
const createdPerson = await Person.create({ name: 'Hafez' });
- const removedPerson = await Person.findOneAndRemove({ _id: createdPerson._id });
+ const removedPerson = await Person.findOneAndDelete({ _id: createdPerson._id });
removedPerson.isNew = true;
@@ -3187,13 +3188,6 @@ describe('document', function() {
assert.equal(doc.child.name, 'Anakin');
});
- it('strings of length 12 are valid oids (gh-3365)', async function() {
- const schema = new Schema({ myId: mongoose.Schema.Types.ObjectId });
- const M = db.model('Test', schema);
- const doc = new M({ myId: 'blablablabla' });
- await doc.validate();
- });
-
it('set() empty obj unmodifies subpaths (gh-4182)', async function() {
const omeletteSchema = new Schema({
topping: {
@@ -9819,7 +9813,7 @@ describe('document', function() {
assert.ok(doc);
});
- it('Makes sure pre remove hook is executed gh-9885', async function() {
+ it('Makes sure pre deleteOne hook is executed (gh-9885)', async function() {
const SubSchema = new Schema({
myValue: {
type: String
@@ -12237,19 +12231,6 @@ describe('document', function() {
assert.equal(fromDb.c.x.y, 1);
});
- it('can change the value of the id property on documents gh-10096', async function() {
- const testSchema = new Schema({
- name: String
- });
- const Test = db.model('Test', testSchema);
- const doc = new Test({ name: 'Test Testerson ' });
- const oldVal = doc.id;
- doc.id = '648b8aa6a97549b03835c0b3';
- await doc.save();
- assert.notEqual(oldVal, doc.id);
- assert.equal(doc.id, '648b8aa6a97549b03835c0b3');
- });
-
it('should allow storing keys with dots in name in mixed under nested (gh-13530)', async function() {
const TestModelSchema = new mongoose.Schema({
metadata:
@@ -12407,6 +12388,20 @@ describe('document', function() {
const nestedProjectionDoc = await User.findOne({}, { name: 1, 'sub.propertyA': 1, 'sub.propertyB': 1 });
assert.strictEqual(nestedProjectionDoc.sub.propertyA, 'A');
});
+
+ it('should ignore `id` if the object contains `id` and `_id` as keys (gh-13762)', async function() {
+ const testSchema = new Schema({
+ _id: {
+ type: Number
+ }
+ });
+ const Test = db.model('Test', testSchema);
+
+ const x = new Test({ _id: 1, id: 2 });
+ await x.save();
+ const fromDb = await Test.findById(x._id).lean();
+ assert.equal(fromDb._id, 1);
+ });
});
describe('Check if instance function that is supplied in schema option is availabe', function() {
diff --git a/test/index.test.js b/test/index.test.js
index 0976aab3479..76ef810c2d1 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -466,7 +466,7 @@ describe('mongoose module:', function() {
const M = mongoose.model('gh6760', schema);
- const doc = new M({ testId: 'length12str0', testNum: 123, mixed: {} });
+ const doc = new M({ testId: '0'.repeat(24), testNum: 123, mixed: {} });
assert.ok(doc.testId instanceof mongoose.Types.ObjectId);
assert.ok(doc.testNum instanceof mongoose.Types.Decimal128);
@@ -739,7 +739,7 @@ describe('mongoose module:', function() {
});
it('isValidObjectId (gh-3823)', function() {
- assert.ok(mongoose.isValidObjectId('0123456789ab'));
+ assert.ok(!mongoose.isValidObjectId('0123456789ab'));
assert.ok(mongoose.isValidObjectId('5f5c2d56f6e911019ec2acdc'));
assert.ok(mongoose.isValidObjectId('608DE01F32B6A93BBA314159'));
assert.ok(mongoose.isValidObjectId(new mongoose.Types.ObjectId()));
@@ -920,7 +920,7 @@ describe('mongoose module:', function() {
const goodIdString = '1'.repeat(24);
assert.deepStrictEqual(mongoose.isValidObjectId(goodIdString), true);
const goodIdString2 = '1'.repeat(12);
- assert.deepStrictEqual(mongoose.isValidObjectId(goodIdString2), true);
+ assert.deepStrictEqual(mongoose.isValidObjectId(goodIdString2), false);
});
it('Allows a syncIndexes shorthand mongoose.syncIndexes (gh-10893)', async function() {
const m = new mongoose.Mongoose();
diff --git a/test/model.create.test.js b/test/model.create.test.js
index 3b2182e8259..d587e70ae16 100644
--- a/test/model.create.test.js
+++ b/test/model.create.test.js
@@ -197,6 +197,20 @@ describe('model', function() {
const docs = await Test.find();
assert.equal(docs.length, 5);
});
+ it('should throw an error only after all the documents have finished saving gh-4628', async function() {
+ const testSchema = new Schema({ name: { type: String, unique: true } });
+
+
+ const Test = db.model('gh4628Test', testSchema);
+ await Test.init();
+ const data = [];
+ for (let i = 0; i < 11; i++) {
+ data.push({ name: 'Test' + Math.abs(i - 4) });
+ }
+ await Test.create(data, { ordered: false }).catch(err => err);
+ const docs = await Test.find();
+ assert.equal(docs.length, 7); // docs 1,2,3,4 should not go through 11-4 == 7
+ });
it('should return the first error immediately if "aggregateErrors" is not explicitly set (ordered)', async function() {
const testSchema = new Schema({ name: { type: String, required: true } });
diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js
index 6f7fd05d4a2..400cf976f63 100644
--- a/test/model.discriminator.test.js
+++ b/test/model.discriminator.test.js
@@ -2180,4 +2180,27 @@ describe('model', function() {
assert.ok(innerBuildingsPath.schemaOptions.type.discriminators.Garage);
assert.equal(innerBuildingsPath.schemaOptions.type.discriminators.Garage.discriminatorMapping.value, 'G');
});
+
+ it('runs base schema paths validators and setters before child schema validators and setters (gh-13794)', async function() {
+ const baseSchema = new Schema({
+ f1: {
+ type: Number,
+ set() {
+ return 1;
+ }
+ }
+ });
+ const childSchema = new Schema({
+ f2: {
+ type: Number,
+ set() {
+ return this.f1;
+ }
+ }
+ });
+ const Test = db.model('Test', baseSchema);
+ const Child = Test.discriminator('Child', childSchema);
+ const doc = new Child({ f1: 2, f2: 2 });
+ assert.strictEqual(doc.f2, 1);
+ });
});
diff --git a/test/model.findOneAndDelete.test.js b/test/model.findOneAndDelete.test.js
index 38986a9ca33..de77c5ceb05 100644
--- a/test/model.findOneAndDelete.test.js
+++ b/test/model.findOneAndDelete.test.js
@@ -350,27 +350,11 @@ describe('model: findOneAndDelete:', function() {
assert.equal(doc.name, 'Test');
await Test.create({ name: 'Test' });
- let data = await Test.findOneAndDelete(
+ const data = await Test.findOneAndDelete(
{ name: 'Test' },
{ includeResultMetadata: true }
);
assert(data.ok);
assert.equal(data.value.name, 'Test');
-
- await Test.create({ name: 'Test' });
- data = await Test.findOneAndDelete(
- { name: 'Test' },
- { includeResultMetadata: true, rawResult: true }
- );
- assert(data.ok);
- assert.equal(data.value.name, 'Test');
-
- await assert.rejects(
- () => Test.findOneAndDelete(
- { name: 'Test' },
- { includeResultMetadata: false, rawResult: true }
- ),
- /Cannot set `rawResult` option when `includeResultMetadata` is false/
- );
});
});
diff --git a/test/model.findOneAndRemove.test.js b/test/model.findOneAndRemove.test.js
deleted file mode 100644
index 667f7115a96..00000000000
--- a/test/model.findOneAndRemove.test.js
+++ /dev/null
@@ -1,349 +0,0 @@
-'use strict';
-
-/**
- * Test dependencies.
- */
-
-const start = require('./common');
-
-const assert = require('assert');
-
-const mongoose = start.mongoose;
-const Schema = mongoose.Schema;
-const ObjectId = Schema.Types.ObjectId;
-const DocumentObjectId = mongoose.Types.ObjectId;
-
-describe('model: findOneAndRemove:', async function() {
- let Comments;
- let BlogPost;
- let db;
-
- before(function() {
- db = start();
- });
-
- after(async function() {
- await db.close();
- });
-
- beforeEach(() => db.deleteModel(/.*/));
- afterEach(() => require('./util').clearTestData(db));
- afterEach(() => require('./util').stopRemainingOps(db));
-
- beforeEach(function() {
- Comments = new Schema();
-
- Comments.add({
- title: String,
- date: Date,
- body: String,
- comments: [Comments]
- });
-
- BlogPost = new Schema({
- title: String,
- author: String,
- slug: String,
- date: Date,
- meta: {
- date: Date,
- visitors: Number
- },
- published: Boolean,
- mixed: {},
- numbers: [Number],
- owners: [ObjectId],
- comments: [Comments]
- });
-
- BlogPost.virtual('titleWithAuthor')
- .get(function() {
- return this.get('title') + ' by ' + this.get('author');
- })
- .set(function(val) {
- const split = val.split(' by ');
- this.set('title', split[0]);
- this.set('author', split[1]);
- });
-
- BlogPost.method('cool', function() {
- return this;
- });
-
- BlogPost.static('woot', function() {
- return this;
- });
-
- BlogPost = db.model('BlogPost', BlogPost);
- });
-
- it('returns the original document', async function() {
- const M = BlogPost;
- const title = 'remove muah';
-
- const post = new M({ title: title });
-
- await post.save();
-
- const doc = await M.findOneAndRemove({ title: title });
-
- assert.equal(post.id, doc.id);
-
- const gone = await M.findById(post.id);
- assert.equal(gone, null);
- });
-
- it('options/conditions/doc are merged when no callback is passed', function(done) {
- const M = BlogPost;
-
- const now = new Date();
- let query;
-
- // Model.findOneAndRemove
- query = M.findOneAndRemove({ author: 'aaron' }, { select: 'author' });
- assert.equal(query._fields.author, 1);
- assert.equal(query._conditions.author, 'aaron');
-
- query = M.findOneAndRemove({ author: 'aaron' });
- assert.equal(query._fields, undefined);
- assert.equal(query._conditions.author, 'aaron');
-
- query = M.findOneAndRemove();
- assert.equal(query.options.new, undefined);
- assert.equal(query._fields, undefined);
- assert.equal(query._conditions.author, undefined);
-
- // Query.findOneAndRemove
- query = M.where('author', 'aaron').findOneAndRemove({ date: now });
- assert.equal(query._fields, undefined);
- assert.equal(query._conditions.date, now);
- assert.equal(query._conditions.author, 'aaron');
-
- query = M.find().findOneAndRemove({ author: 'aaron' }, { select: 'author' });
- assert.equal(query._fields.author, 1);
- assert.equal(query._conditions.author, 'aaron');
-
- query = M.find().findOneAndRemove();
- assert.equal(query._fields, undefined);
- assert.equal(query._conditions.author, undefined);
- done();
- });
-
- it('returns the original document', async function() {
- const M = BlogPost;
- const title = 'remove muah pleez';
-
- const post = new M({ title: title });
- await post.save();
- const doc = await M.findByIdAndRemove(post.id);
- assert.equal(post.id, doc.id);
- const gone = await M.findById(post.id);
- assert.equal(gone, null);
- });
-
- it('options/conditions/doc are merged when no callback is passed', function(done) {
- const M = BlogPost;
- const _id = new DocumentObjectId();
-
- let query;
-
- // Model.findByIdAndRemove
- query = M.findByIdAndRemove(_id, { select: 'author' });
- assert.equal(query._fields.author, 1);
- assert.equal(query._conditions._id.toString(), _id.toString());
-
- query = M.findByIdAndRemove(_id.toString());
- assert.equal(query._fields, undefined);
- assert.equal(query._conditions._id, _id.toString());
-
- query = M.findByIdAndRemove();
- assert.equal(query.options.new, undefined);
- assert.equal(query._fields, undefined);
- assert.equal(query._conditions._id, undefined);
- done();
- });
-
- it('supports v3 select string syntax', function(done) {
- const M = BlogPost;
- const _id = new DocumentObjectId();
-
- let query;
-
- query = M.findByIdAndRemove(_id, { select: 'author -title' });
- query._applyPaths();
- assert.strictEqual(1, query._fields.author);
- assert.strictEqual(0, query._fields.title);
-
- query = M.findOneAndRemove({}, { select: 'author -title' });
- query._applyPaths();
- assert.strictEqual(1, query._fields.author);
- assert.strictEqual(0, query._fields.title);
- done();
- });
-
- it('supports v3 select object syntax', function(done) {
- const M = BlogPost;
- const _id = new DocumentObjectId();
-
- let query;
-
- query = M.findByIdAndRemove(_id, { select: { author: 1, title: 0 } });
- assert.strictEqual(1, query._fields.author);
- assert.strictEqual(0, query._fields.title);
-
- query = M.findOneAndRemove({}, { select: { author: 1, title: 0 } });
- assert.strictEqual(1, query._fields.author);
- assert.strictEqual(0, query._fields.title);
- done();
- });
-
- it('supports v3 sort string syntax', function(done) {
- const M = BlogPost;
- const _id = new DocumentObjectId();
-
- let query;
-
- query = M.findByIdAndRemove(_id, { sort: 'author -title' });
- assert.equal(Object.keys(query.options.sort).length, 2);
- assert.equal(query.options.sort.author, 1);
- assert.equal(query.options.sort.title, -1);
-
- query = M.findOneAndRemove({}, { sort: 'author -title' });
- assert.equal(Object.keys(query.options.sort).length, 2);
- assert.equal(query.options.sort.author, 1);
- assert.equal(query.options.sort.title, -1);
- done();
- });
-
- it('supports v3 sort object syntax', function(done) {
- const M = BlogPost;
- const _id = new DocumentObjectId();
-
- let query;
-
- query = M.findByIdAndRemove(_id, { sort: { author: 1, title: -1 } });
- assert.equal(Object.keys(query.options.sort).length, 2);
- assert.equal(query.options.sort.author, 1);
- assert.equal(query.options.sort.title, -1);
-
- query = M.findOneAndRemove(_id, { sort: { author: 1, title: -1 } });
- assert.equal(Object.keys(query.options.sort).length, 2);
- assert.equal(query.options.sort.author, 1);
- assert.equal(query.options.sort.title, -1);
- done();
- });
-
- it('supports population (gh-1395)', async function() {
- const M = db.model('Test1', { name: String });
- const N = db.model('Test2', { a: { type: Schema.ObjectId, ref: 'Test1' }, i: Number });
-
- const a = await M.create({ name: 'i am an A' });
- const b = await N.create({ a: a._id, i: 10 });
-
- const doc = await N.findOneAndRemove({ _id: b._id }, { select: 'a -_id' })
- .populate('a')
- .exec();
-
- assert.ok(doc);
- assert.equal(doc._id, undefined);
- assert.ok(doc.a);
- assert.equal('i am an A', doc.a.name);
- });
-
- it('only calls setters once (gh-6203)', async function() {
-
- const calls = [];
- const userSchema = new mongoose.Schema({
- name: String,
- foo: {
- type: String,
- set: function(val) {
- calls.push(val);
- return val + val;
- }
- }
- });
- const Model = db.model('Test', userSchema);
-
- await Model.findOneAndRemove({ foo: '123' }, { name: 'bar' });
-
- assert.deepEqual(calls, ['123']);
- });
-
- it('with orFail() (gh-9381)', function() {
- const User = db.model('User', Schema({ name: String }));
-
- return User.findOneAndRemove({ name: 'not found' }).orFail().
- then(() => null, err => err).
- then(err => {
- assert.ok(err);
- assert.equal(err.name, 'DocumentNotFoundError');
- });
- });
-
- describe('middleware', function() {
-
- it('works', async function() {
- const s = new Schema({
- topping: { type: String, default: 'bacon' },
- base: String
- });
-
- let preCount = 0;
- s.pre('findOneAndRemove', function() {
- ++preCount;
- });
-
- let postCount = 0;
- s.post('findOneAndRemove', function() {
- ++postCount;
- });
-
- const Breakfast = db.model('Test', s);
- const breakfast = new Breakfast({
- base: 'eggs'
- });
-
- await breakfast.save();
-
- const breakfast2 = await Breakfast.findOneAndRemove(
- { base: 'eggs' },
- {}
- );
-
- assert.equal(breakfast2.base, 'eggs');
- assert.equal(preCount, 1);
- assert.equal(postCount, 1);
- });
-
- it('works with exec() (gh-439)', async() => {
- const s = new Schema({
- topping: { type: String, default: 'bacon' },
- base: String
- });
-
- let preCount = 0;
- s.pre('findOneAndRemove', function() {
- ++preCount;
- });
-
- let postCount = 0;
- s.post('findOneAndRemove', function() {
- ++postCount;
- });
-
- const Breakfast = db.model('Test', s);
- const breakfast = new Breakfast({
- base: 'eggs'
- });
-
- await breakfast.save();
-
- const breakfast2 = await Breakfast.findOneAndRemove({ base: 'eggs' }, {});
-
- assert.equal(breakfast2.base, 'eggs');
- assert.equal(preCount, 1);
- assert.equal(postCount, 1);
- });
- });
-});
diff --git a/test/model.findOneAndReplace.test.js b/test/model.findOneAndReplace.test.js
index 5550f198915..e8fa3764ca4 100644
--- a/test/model.findOneAndReplace.test.js
+++ b/test/model.findOneAndReplace.test.js
@@ -468,29 +468,12 @@ describe('model: findOneAndReplace:', function() {
assert.equal(doc.ok, undefined);
assert.equal(doc.name, 'Test Testerson');
- let data = await Test.findOneAndReplace(
+ const data = await Test.findOneAndReplace(
{ name: 'Test Testerson' },
{ name: 'Test' },
{ new: true, upsert: true, includeResultMetadata: true }
);
assert(data.ok);
assert.equal(data.value.name, 'Test');
-
- data = await Test.findOneAndReplace(
- { name: 'Test Testerson' },
- { name: 'Test' },
- { new: true, upsert: true, includeResultMetadata: true, rawResult: true }
- );
- assert(data.ok);
- assert.equal(data.value.name, 'Test');
-
- await assert.rejects(
- () => Test.findOneAndReplace(
- { name: 'Test Testerson' },
- { name: 'Test' },
- { new: true, upsert: true, includeResultMetadata: false, rawResult: true }
- ),
- /Cannot set `rawResult` option when `includeResultMetadata` is false/
- );
});
});
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index eee320aa968..ab3121a2581 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -666,7 +666,7 @@ describe('model: findOneAndUpdate:', function() {
assert.ok(fruit instanceof mongoose.Document);
});
- it('return rawResult when doing an upsert & new=false gh-7770', async function() {
+ it('return includeResultMetadata when doing an upsert & new=false gh-7770', async function() {
const thingSchema = new Schema({
_id: String,
flag: {
@@ -678,13 +678,13 @@ describe('model: findOneAndUpdate:', function() {
const Thing = db.model('Test', thingSchema);
const key = 'some-new-id';
- const rawResult = await Thing.findOneAndUpdate({ _id: key }, { $set: { flag: false } }, { upsert: true, new: false, rawResult: true }).exec();
- assert.equal(rawResult.lastErrorObject.updatedExisting, false);
+ const res1 = await Thing.findOneAndUpdate({ _id: key }, { $set: { flag: false } }, { upsert: true, new: false, includeResultMetadata: true }).exec();
+ assert.equal(res1.lastErrorObject.updatedExisting, false);
- const rawResult2 = await Thing.findOneAndUpdate({ _id: key }, { $set: { flag: true } }, { upsert: true, new: false, rawResult: true }).exec();
- assert.equal(rawResult2.lastErrorObject.updatedExisting, true);
- assert.equal(rawResult2.value._id, key);
- assert.equal(rawResult2.value.flag, false);
+ const res2 = await Thing.findOneAndUpdate({ _id: key }, { $set: { flag: true } }, { upsert: true, new: false, includeResultMetadata: true }).exec();
+ assert.equal(res2.lastErrorObject.updatedExisting, true);
+ assert.equal(res2.value._id, key);
+ assert.equal(res2.value.flag, false);
});
@@ -1261,13 +1261,13 @@ describe('model: findOneAndUpdate:', function() {
});
describe('bug fixes', function() {
- it('passes raw result if rawResult specified (gh-4925)', async function() {
+ it('passes raw result if includeResultMetadata specified (gh-4925)', async function() {
const testSchema = new mongoose.Schema({
test: String
});
const TestModel = db.model('Test', testSchema);
- const options = { upsert: true, new: true, rawResult: true };
+ const options = { upsert: true, new: true, includeResultMetadata: true };
const update = { $set: { test: 'abc' } };
const res = await TestModel.findOneAndUpdate({}, update, options).exec();
@@ -2159,30 +2159,13 @@ describe('model: findOneAndUpdate:', function() {
assert.equal(doc.ok, undefined);
assert.equal(doc.name, 'Test Testerson');
- let data = await Test.findOneAndUpdate(
+ const data = await Test.findOneAndUpdate(
{ name: 'Test Testerson' },
{ name: 'Test' },
{ new: true, upsert: true, includeResultMetadata: true }
);
assert(data.ok);
assert.equal(data.value.name, 'Test');
-
- data = await Test.findOneAndUpdate(
- { name: 'Test Testerson' },
- { name: 'Test' },
- { new: true, upsert: true, includeResultMetadata: true, rawResult: true }
- );
- assert(data.ok);
- assert.equal(data.value.name, 'Test');
-
- await assert.rejects(
- () => Test.findOneAndUpdate(
- { name: 'Test Testerson' },
- { name: 'Test' },
- { new: true, upsert: true, includeResultMetadata: false, rawResult: true }
- ),
- /Cannot set `rawResult` option when `includeResultMetadata` is false/
- );
});
it('successfully runs findOneAndUpdate with no update and versionKey set to false (gh-13783)', async function() {
diff --git a/test/model.middleware.preposttypes.test.js b/test/model.middleware.preposttypes.test.js
index 2a2e3323cb4..952bc901001 100644
--- a/test/model.middleware.preposttypes.test.js
+++ b/test/model.middleware.preposttypes.test.js
@@ -185,9 +185,9 @@ describe('pre/post hooks, type of this', function() {
const MongooseDocumentMiddleware = [...MongooseDistinctDocumentMiddleware, ...MongooseQueryAndDocumentMiddleware];
const MongooseDistinctQueryMiddleware = [
- 'count', 'estimatedDocumentCount', 'countDocuments',
+ 'estimatedDocumentCount', 'countDocuments',
'deleteMany', 'distinct',
- 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate',
+ 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate',
'replaceOne', 'updateMany'];
const MongooseDefaultQueryMiddleware = [...MongooseDistinctQueryMiddleware, 'updateOne', 'deleteOne'];
const MongooseQueryMiddleware = [...MongooseDistinctQueryMiddleware, ...MongooseQueryAndDocumentMiddleware];
@@ -278,7 +278,6 @@ describe('pre/post hooks, type of this', function() {
await doc.save(); // triggers save and validate hooks
// MongooseDistinctQueryMiddleware
- await Doc.count().exec();
await Doc.estimatedDocumentCount().exec();
await Doc.countDocuments().exec();
await Doc.deleteMany().exec(); await Doc.create({ data: 'value' });
@@ -286,7 +285,6 @@ describe('pre/post hooks, type of this', function() {
await Doc.find({}).exec();
await Doc.findOne({}).exec();
await Doc.findOneAndDelete({}).exec(); await Doc.create({ data: 'value' });
- await Doc.findOneAndRemove({}).exec(); await Doc.create({ data: 'value' });
await Doc.findOneAndReplace({}, { data: 'valueRep' }).exec();
await Doc.findOneAndUpdate({}, { data: 'valueUpd' }).exec();
await Doc.replaceOne({}, { data: 'value' }).exec();
diff --git a/test/model.middleware.test.js b/test/model.middleware.test.js
index 645a6beb1d2..7747167bb4b 100644
--- a/test/model.middleware.test.js
+++ b/test/model.middleware.test.js
@@ -447,13 +447,13 @@ describe('model middleware', function() {
await doc.deleteOne();
- assert.equal(queryPreCalled, 0);
+ assert.equal(queryPreCalled, 1);
assert.equal(preCalled, 1);
assert.equal(postCalled, 1);
await Model.deleteOne();
- assert.equal(queryPreCalled, 1);
+ assert.equal(queryPreCalled, 2);
assert.equal(preCalled, 1);
assert.equal(postCalled, 1);
});
diff --git a/test/model.test.js b/test/model.test.js
index 013a0766688..0a0903715cc 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -1177,8 +1177,12 @@ describe('Model', function() {
it('errors when id deselected (gh-3118)', async function() {
await BlogPost.create({ title: 1 }, { title: 2 });
const doc = await BlogPost.findOne({ title: 1 }, { _id: 0 });
- const err = await doc.deleteOne().then(() => null, err => err);
- assert.equal(err.message, 'No _id found on document!');
+ try {
+ await doc.deleteOne();
+ assert.ok(false);
+ } catch (err) {
+ assert.equal(err.message, 'No _id found on document!');
+ }
});
it('should not remove any records when deleting by id undefined', async function() {
@@ -2319,7 +2323,7 @@ describe('Model', function() {
const title = 'interop ad-hoc as promise';
const created = await BlogPost.create({ title: title });
- const query = BlogPost.count({ title: title });
+ const query = BlogPost.countDocuments({ title: title });
const found = await query.exec('findOne');
assert.equal(found.id, created.id);
});
@@ -5046,10 +5050,6 @@ describe('Model', function() {
await Model.createCollection();
const collectionName = Model.collection.name;
- // If the collection is not created, the following will throw
- // MongoServerError: Collection [mongoose_test.User] not found.
- await db.collection(collectionName).stats();
-
await Model.create([{ name: 'alpha' }, { name: 'Zeta' }]);
// Ensure that the default collation is set. Mongoose will set the
@@ -5318,7 +5318,7 @@ describe('Model', function() {
}
]);
- const beforeExpirationCount = await Test.count({});
+ const beforeExpirationCount = await Test.countDocuments({});
assert.ok(beforeExpirationCount === 12);
let intervalid;
@@ -5332,7 +5332,7 @@ describe('Model', function() {
// in case it happens faster, to reduce test time
new Promise(resolve => {
intervalid = setInterval(async() => {
- const count = await Test.count({});
+ const count = await Test.countDocuments({});
if (count === 0) {
resolve();
}
@@ -5342,7 +5342,7 @@ describe('Model', function() {
clearInterval(intervalid);
- const afterExpirationCount = await Test.count({});
+ const afterExpirationCount = await Test.countDocuments({});
assert.equal(afterExpirationCount, 0);
});
@@ -5472,7 +5472,6 @@ describe('Model', function() {
await doc.deleteOne({ session });
assert.equal(sessions.length, 1);
assert.strictEqual(sessions[0], session);
-
});
it('set $session() before pre validate hooks run on bulkWrite and insertMany (gh-7769)', async function() {
diff --git a/test/model.validate.test.js b/test/model.validate.test.js
index d69d2d69a02..cc95e69819f 100644
--- a/test/model.validate.test.js
+++ b/test/model.validate.test.js
@@ -57,7 +57,7 @@ describe('model: validate: ', function() {
assert.deepEqual(Object.keys(err.errors), ['comments.name']);
obj = { age: '42' };
- await Model.validate(obj, ['age']);
+ obj = await Model.validate(obj, ['age']);
assert.strictEqual(obj.age, 42);
});
@@ -106,7 +106,7 @@ describe('model: validate: ', function() {
const test = { docs: ['6132655f2cdb9d94eaebc09b'] };
- const err = await Test.validate(test);
+ const err = await Test.validate(test).then(() => null, err => err);
assert.ifError(err);
});
@@ -124,7 +124,7 @@ describe('model: validate: ', function() {
const User = mongoose.model('User', userSchema);
const user = new User({ name: 'test', nameRequired: false });
- const err = await User.validate(user).catch(err => err);
+ const err = await User.validate(user).then(() => null, err => err);
assert.ifError(err);
@@ -181,6 +181,29 @@ describe('model: validate: ', function() {
await assert.rejects(async() => {
await Test.validate(test, pathsOrOptions);
}, { message: 'Validation failed: name: Validator failed for path `name` with value `1`' });
+ });
+ it('runs validation on casted paths even if cast error happened', async function() {
+ const Model = mongoose.model('Test', new Schema({
+ invalid1: {
+ type: String,
+ validate: () => false
+ },
+ myNumber: {
+ type: Number,
+ required: true
+ },
+ invalid2: {
+ type: String,
+ validate: () => false
+ }
+ }));
+
+ const err = await Model.validate({ invalid1: 'foo', myNumber: 'not a number', invalid2: 'bar' }).
+ then(() => null, err => err);
+ assert.ok(err);
+ assert.deepEqual(Object.keys(err.errors).sort(), ['invalid1', 'invalid2', 'myNumber']);
+ assert.equal(err.errors['myNumber'].name, 'CastError');
+ assert.equal(err.errors['invalid1'].name, 'ValidatorError');
});
});
diff --git a/test/query.test.js b/test/query.test.js
index 13dbd36177b..d018c5fee77 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -772,12 +772,9 @@ describe('Query', function() {
query.sort({ a: 1, c: -1, b: 'asc', e: 'descending', f: 'ascending' });
assert.deepEqual(query.options.sort, { a: 1, c: -1, b: 1, e: -1, f: 1 });
- if (typeof global.Map !== 'undefined') {
- query = new Query({});
- query.sort(new global.Map().set('a', 1).set('b', 1));
- assert.equal(query.options.sort.get('a'), 1);
- assert.equal(query.options.sort.get('b'), 1);
- }
+ query = new Query({});
+ query.sort(new Map().set('a', 1).set('b', 1));
+ assert.deepStrictEqual(query.options.sort, { a: 1, b: 1 });
query = new Query({});
let e;
@@ -1916,10 +1913,9 @@ describe('Query', function() {
const TestSchema = new Schema({ name: String });
const ops = [
- 'count',
'find',
'findOne',
- 'findOneAndRemove',
+ 'findOneAndDelete',
'findOneAndUpdate',
'replaceOne',
'updateOne',
diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js
index 1de9f78f152..1b1cadb0d6c 100644
--- a/test/query.toconstructor.test.js
+++ b/test/query.toconstructor.test.js
@@ -180,7 +180,7 @@ describe('Query:', function() {
const query = Model.find().sort([['name', 1]]);
const Query = query.toConstructor();
const q = new Query();
- assert.deepEqual(q.options.sort, [['name', 1]]);
+ assert.deepEqual(q.options.sort, { name: 1 });
});
});
});
diff --git a/test/queryhelpers.test.js b/test/queryhelpers.test.js
index 7243086ba02..62c1b2e4afb 100644
--- a/test/queryhelpers.test.js
+++ b/test/queryhelpers.test.js
@@ -4,7 +4,7 @@ require('./common');
const Schema = require('../lib/schema');
const assert = require('assert');
-const queryhelpers = require('../lib/queryhelpers');
+const queryhelpers = require('../lib/queryHelpers');
describe('queryhelpers', function() {
describe('applyPaths', function() {
diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index a6a2ae29a32..70631978c76 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -57,10 +57,10 @@ describe('schema select option', function() {
assert.equal(findUpdateDoc.isSelected('name'), false);
assert.equal(findUpdateDoc.isSelected('docs.name'), false);
assert.strictEqual(undefined, findUpdateDoc.name);
- const findAndRemoveDoc = await Test.findOneAndRemove({ _id: doc._id });
- assert.equal(findAndRemoveDoc.isSelected('name'), false);
- assert.equal(findAndRemoveDoc.isSelected('docs.name'), false);
- assert.strictEqual(undefined, findAndRemoveDoc.name);
+ const findAndDeleteDoc = await Test.findOneAndDelete({ _id: doc._id });
+ assert.equal(findAndDeleteDoc.isSelected('name'), false);
+ assert.equal(findAndDeleteDoc.isSelected('docs.name'), false);
+ assert.strictEqual(undefined, findAndDeleteDoc.name);
});
it('including paths through schematype', async function() {
@@ -87,10 +87,10 @@ describe('schema select option', function() {
assert.strictEqual(true, findOneAndUpdateDoc.isSelected('name'));
assert.strictEqual(true, findOneAndUpdateDoc.isSelected('docs.name'));
assert.equal(findOneAndUpdateDoc.name, 'the included');
- const findOneAndRemoveDoc = await S.findOneAndRemove({ _id: doc._id });
- assert.strictEqual(true, findOneAndRemoveDoc.isSelected('name'));
- assert.strictEqual(true, findOneAndRemoveDoc.isSelected('docs.name'));
- assert.equal(findOneAndRemoveDoc.name, 'the included');
+ const findOneAndDeleteDoc = await S.findOneAndDelete({ _id: doc._id });
+ assert.strictEqual(true, findOneAndDeleteDoc.isSelected('name'));
+ assert.strictEqual(true, findOneAndDeleteDoc.isSelected('docs.name'));
+ assert.equal(findOneAndDeleteDoc.name, 'the included');
});
describe('overriding schematype select options', function() {
@@ -210,16 +210,16 @@ describe('schema select option', function() {
assert.ok(findOneAndUpdateDoc.thin);
assert.ok(findOneAndUpdateDoc.docs[0].bool);
});
- it('with findOneAndRemove', async function() {
- const findOneAndRemoveDoc = await E.findOneAndRemove({ _id: exclusionDoc._id }).select('-name -docs.name');
- assert.equal(findOneAndRemoveDoc.isSelected('name'), false);
- assert.equal(findOneAndRemoveDoc.isSelected('thin'), true);
- assert.equal(findOneAndRemoveDoc.isSelected('docs.name'), false);
- assert.equal(findOneAndRemoveDoc.isSelected('docs.bool'), true);
- assert.strictEqual(undefined, findOneAndRemoveDoc.name);
- assert.strictEqual(undefined, findOneAndRemoveDoc.docs[0].name);
- assert.strictEqual(true, findOneAndRemoveDoc.thin);
- assert.strictEqual(true, findOneAndRemoveDoc.docs[0].bool);
+ it('with findOneAndDelete', async function() {
+ const findOneAndDeleteDoc = await E.findOneAndDelete({ _id: exclusionDoc._id }).select('-name -docs.name');
+ assert.equal(findOneAndDeleteDoc.isSelected('name'), false);
+ assert.equal(findOneAndDeleteDoc.isSelected('thin'), true);
+ assert.equal(findOneAndDeleteDoc.isSelected('docs.name'), false);
+ assert.equal(findOneAndDeleteDoc.isSelected('docs.bool'), true);
+ assert.strictEqual(undefined, findOneAndDeleteDoc.name);
+ assert.strictEqual(undefined, findOneAndDeleteDoc.docs[0].name);
+ assert.strictEqual(true, findOneAndDeleteDoc.thin);
+ assert.strictEqual(true, findOneAndDeleteDoc.docs[0].bool);
});
});
});
diff --git a/test/schema.test.js b/test/schema.test.js
index 1f7a028f1b8..495a79393a2 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -1437,7 +1437,7 @@ describe('schema', function() {
}
};
const s = new Schema(TestSchema, { typeKey: '$type' });
- assert.equal(s.path('action').constructor.name, 'SubdocumentPath');
+ assert.equal(s.path('action').constructor.name, 'SchemaSubdocument');
assert.ok(s.path('action').schema.$implicitlyCreated);
assert.equal(s.path('action.type').constructor.name, 'SchemaString');
});
@@ -2650,7 +2650,7 @@ describe('schema', function() {
myStr: { type: String, cast: v => '' + v }
});
- assert.equal(schema.path('myId').cast('12charstring').toHexString(), '313263686172737472696e67');
+ assert.equal(schema.path('myId').cast('0'.repeat(24)).toHexString(), '0'.repeat(24));
assert.equal(schema.path('myNum').cast(3.14), 4);
assert.equal(schema.path('myDate').cast('2012-06-01').getFullYear(), 2012);
assert.equal(schema.path('myBool').cast('hello'), true);
diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js
index c0a18a8835a..d70643c1825 100644
--- a/test/schema.validation.test.js
+++ b/test/schema.validation.test.js
@@ -827,6 +827,19 @@ describe('schema', function() {
}
});
+ it('should allow null values for enum gh-3044', async function() {
+ const testSchema = new Schema({
+ name: {
+ type: String,
+ enum: ['test']
+ }
+ });
+ const Test = mongoose.model('allow-null' + random(), testSchema);
+ const a = new Test({ name: null });
+ const err = await a.validate().then(() => null, err => err);
+ assert.equal(err, null);
+ });
+
it('should allow an array of subdocuments with enums (gh-3521)', async function() {
const coolSchema = new Schema({
votes: [{
diff --git a/test/schematype.cast.test.js b/test/schematype.cast.test.js
index acf2658f3af..77f28e2d9a7 100644
--- a/test/schematype.cast.test.js
+++ b/test/schematype.cast.test.js
@@ -29,6 +29,9 @@ describe('SchemaType.cast() (gh-7045)', function() {
class CustomObjectId extends Schema.ObjectId {}
CustomObjectId.cast(v => {
+ if (v === 'special') {
+ return original.objectid('0'.repeat(24));
+ }
assert.ok(v == null || (typeof v === 'string' && v.length === 24));
return original.objectid(v);
});
@@ -38,7 +41,7 @@ describe('SchemaType.cast() (gh-7045)', function() {
let threw = false;
try {
- objectid.cast('12charstring');
+ baseObjectId.cast('special');
} catch (error) {
threw = true;
assert.equal(error.name, 'CastError');
@@ -46,7 +49,7 @@ describe('SchemaType.cast() (gh-7045)', function() {
assert.doesNotThrow(function() {
objectid.cast('000000000000000000000000');
- baseObjectId.cast('12charstring');
+ objectid.cast('special');
baseObjectId.cast('000000000000000000000000');
});
diff --git a/test/schematype.test.js b/test/schematype.test.js
index 13eb8c5dce4..38691d645ae 100644
--- a/test/schematype.test.js
+++ b/test/schematype.test.js
@@ -235,7 +235,7 @@ describe('schematype', function() {
});
const typesToTest = Object.values(mongoose.SchemaTypes).
- filter(t => t.name !== 'SubdocumentPath' && t.name !== 'DocumentArrayPath');
+ filter(t => t.name !== 'SchemaSubdocument' && t.name !== 'SchemaDocumentArray');
typesToTest.forEach((type) => {
it(type.name + ', when given a default option, set its', () => {
diff --git a/test/types/middleware.preposttypes.test.ts b/test/types/middleware.preposttypes.test.ts
index 6ee1ec35017..006adb2dd6f 100644
--- a/test/types/middleware.preposttypes.test.ts
+++ b/test/types/middleware.preposttypes.test.ts
@@ -468,51 +468,6 @@ schema.post('findOneAndDelete', { document: false, query: false }, function(res)
expectNotType>(res);
});
-schema.pre('findOneAndRemove', function() {
- expectType>(this);
-});
-
-schema.post('findOneAndRemove', function(res) {
- expectType>(this);
- expectNotType>(res);
-});
-
-schema.pre('findOneAndRemove', { document: false, query: true }, function() {
- expectType>(this);
-});
-
-schema.post('findOneAndRemove', { document: false, query: true }, function(res) {
- expectType>(this);
- expectNotType>(res);
-});
-
-schema.pre('findOneAndRemove', { document: true, query: true }, function() {
- expectType>(this);
-});
-
-schema.post('findOneAndRemove', { document: true, query: true }, function(res) {
- expectType>(this);
- expectNotType>(res);
-});
-
-schema.pre('findOneAndRemove', { document: true, query: false }, function() {
- expectType(this);
-});
-
-schema.post('findOneAndRemove', { document: true, query: false }, function(res) {
- expectType(this);
- expectNotType>(res);
-});
-
-schema.pre('findOneAndRemove', { document: false, query: false }, function() {
- expectType(this);
-});
-
-schema.post('findOneAndRemove', { document: false, query: false }, function(res) {
- expectType(this);
- expectNotType>(res);
-});
-
schema.pre('findOneAndReplace', function() {
expectType>(this);
});
@@ -828,92 +783,92 @@ schema.post(['save', 'init'], { document: false, query: false }, function(res) {
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: true }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: true }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: true }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: true }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: false }, function() {
expectType(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: true, query: false }, function(res) {
expectType(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: false }, function() {
expectType(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], { document: false, query: false }, function(res) {
expectType(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: true }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: true }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: false }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: false }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: true }, function() {
expectType|HydratedDocument>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: true, query: true }, function(res) {
expectType|HydratedDocument>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: false }, function() {
expectType(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne'], { document: false, query: false }, function(res) {
expectType(this);
expectNotType>(res);
});
@@ -963,92 +918,92 @@ schema.post(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document:
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function() {
expectType|HydratedDocument>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function(res) {
expectType|HydratedDocument>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
expectType|HydratedDocument>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
expectType|HydratedDocument>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
expectType(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
expectType(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], function() {
expectType|HydratedDocument>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], function(res) {
expectType|HydratedDocument>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
expectType>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
expectType>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
expectType|HydratedDocument>(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
expectType|HydratedDocument>(this);
expectNotType>(res);
});
-schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
+schema.pre(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
expectType(this);
});
-schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndRemove', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
+schema.post(['count', 'estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
expectType(this);
expectNotType>(res);
});
diff --git a/test/types/queries.test.ts b/test/types/queries.test.ts
index efca12618a5..ff5f7c18cba 100644
--- a/test/types/queries.test.ts
+++ b/test/types/queries.test.ts
@@ -115,10 +115,10 @@ Test.findOneAndUpdate({ name: 'test' }, { name: 'test3' }, { upsert: true, new:
Test.findOneAndUpdate({ name: 'test' }, { name: 'test3' }, { upsert: true, returnOriginal: false }).then((res: ITest) => {
res.name = 'test4';
});
-Test.findOneAndUpdate({ name: 'test' }, { name: 'test3' }, { rawResult: true }).then((res: any) => {
+Test.findOneAndUpdate({ name: 'test' }, { name: 'test3' }, { includeResultMetadata: true }).then((res: any) => {
console.log(res.ok);
});
-Test.findOneAndUpdate({ name: 'test' }, { name: 'test3' }, { new: true, upsert: true, rawResult: true }).then((res: any) => {
+Test.findOneAndUpdate({ name: 'test' }, { name: 'test3' }, { new: true, upsert: true, includeResultMetadata: true }).then((res: any) => {
console.log(res.ok);
});
@@ -295,8 +295,9 @@ async function gh11306(): Promise {
// 3. Create a Model.
const MyModel = model('User', schema);
- expectType(await MyModel.distinct('name'));
- expectType(await MyModel.distinct('name'));
+ expectType(await MyModel.distinct('notThereInSchema'));
+ expectType(await MyModel.distinct('name'));
+ expectType(await MyModel.distinct<'overrideTest', number>('overrideTest'));
}
function autoTypedQuery() {
@@ -422,7 +423,7 @@ async function gh11602(): Promise {
const updateResult = await ModelType.findOneAndUpdate(query, { $inc: { occurence: 1 } }, {
upsert: true,
returnDocument: 'after',
- rawResult: true
+ includeResultMetadata: true
});
expectError(updateResult.lastErrorObject?.modifiedCount);
diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts
index 16f58ed938b..fc0204e2a71 100644
--- a/test/types/schema.test.ts
+++ b/test/types/schema.test.ts
@@ -1218,3 +1218,15 @@ function gh13800() {
expectError(this.someOtherField);
});
}
+
+async function gh13797() {
+ interface IUser {
+ name: string;
+ }
+ new Schema({ name: { type: String, required: function() {
+ expectType(this); return true;
+ } } });
+ new Schema({ name: { type: String, default: function() {
+ expectType(this); return '';
+ } } });
+}
diff --git a/test/utils.test.js b/test/utils.test.js
index fe321b424c6..648512fb877 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -8,7 +8,7 @@ const start = require('./common');
const MongooseBuffer = require('../lib/types/buffer');
const ObjectId = require('../lib/types/objectid');
-const StateMachine = require('../lib/statemachine');
+const StateMachine = require('../lib/stateMachine');
const assert = require('assert');
const utils = require('../lib/utils');
diff --git a/types/index.d.ts b/types/index.d.ts
index 840a3634e16..1bd4b0a7085 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -236,7 +236,7 @@ declare module 'mongoose' {
/**
* Create a new schema
*/
- constructor(definition?: SchemaDefinition> | DocType, options?: SchemaOptions | ResolveSchemaOptions);
+ constructor(definition?: SchemaDefinition, EnforcedDocType> | DocType, options?: SchemaOptions | ResolveSchemaOptions);
/** Adds key path / schema type pairs to this schema. */
add(obj: SchemaDefinition> | Schema, prefix?: string): this;
@@ -300,7 +300,7 @@ declare module 'mongoose' {
methods: { [F in keyof TInstanceMethods]: TInstanceMethods[F] } & AnyObject;
/** The original object passed to the schema constructor */
- obj: SchemaDefinition>;
+ obj: SchemaDefinition, EnforcedDocType>;
/** Gets/sets schema paths. */
path>(path: string): ResultType;
@@ -484,26 +484,26 @@ declare module 'mongoose' {
? DateSchemaDefinition
: (Function | string);
- export type SchemaDefinitionProperty = SchemaDefinitionWithBuiltInClass |
- SchemaTypeOptions |
+ export type SchemaDefinitionProperty = SchemaDefinitionWithBuiltInClass |
+ SchemaTypeOptions |
typeof SchemaType |
Schema |
Schema[] |
- SchemaTypeOptions>[] |
+ SchemaTypeOptions, EnforcedDocType>[] |
Function[] |
- SchemaDefinition |
- SchemaDefinition>[] |
+ SchemaDefinition |
+ SchemaDefinition, EnforcedDocType>[] |
typeof Schema.Types.Mixed |
- MixedSchemaTypeOptions;
+ MixedSchemaTypeOptions;
- export type SchemaDefinition = T extends undefined
+ export type SchemaDefinition = T extends undefined
? { [path: string]: SchemaDefinitionProperty; }
- : { [path in keyof T]?: SchemaDefinitionProperty; };
+ : { [path in keyof T]?: SchemaDefinitionProperty; };
export type AnyArray = T[] | ReadonlyArray;
export type ExtractMongooseArray = T extends Types.Array ? AnyArray> : T;
- export interface MixedSchemaTypeOptions extends SchemaTypeOptions {
+ export interface MixedSchemaTypeOptions extends SchemaTypeOptions {
type: typeof Schema.Types.Mixed;
}
diff --git a/types/middlewares.d.ts b/types/middlewares.d.ts
index 43ca1974b81..2d305252908 100644
--- a/types/middlewares.d.ts
+++ b/types/middlewares.d.ts
@@ -5,7 +5,7 @@ declare module 'mongoose' {
type MongooseDistinctDocumentMiddleware = 'save' | 'init' | 'validate';
type MongooseDocumentMiddleware = MongooseDistinctDocumentMiddleware | MongooseQueryAndDocumentMiddleware;
- type MongooseDistinctQueryMiddleware = 'count' | 'estimatedDocumentCount' | 'countDocuments' | 'deleteMany' | 'distinct' | 'find' | 'findOne' | 'findOneAndDelete' | 'findOneAndRemove' | 'findOneAndReplace' | 'findOneAndUpdate' | 'replaceOne' | 'updateMany';
+ type MongooseDistinctQueryMiddleware = 'count' | 'estimatedDocumentCount' | 'countDocuments' | 'deleteMany' | 'distinct' | 'find' | 'findOne' | 'findOneAndDelete' | 'findOneAndReplace' | 'findOneAndUpdate' | 'replaceOne' | 'updateMany';
type MongooseDefaultQueryMiddleware = MongooseDistinctQueryMiddleware | 'updateOne' | 'deleteOne';
type MongooseQueryMiddleware = MongooseDistinctQueryMiddleware | MongooseQueryAndDocumentMiddleware;
diff --git a/types/models.d.ts b/types/models.d.ts
index 2b0a5989445..6af56a5656d 100644
--- a/types/models.d.ts
+++ b/types/models.d.ts
@@ -443,8 +443,11 @@ declare module 'mongoose' {
translateAliases(raw: any): any;
/** Creates a `distinct` query: returns the distinct values of the given `field` that match `filter`. */
- distinct(field: string, filter?: FilterQuery): QueryWithHelpers<
- Array,
+ distinct(
+ field: DocKey,
+ filter?: FilterQuery
+ ): QueryWithHelpers<
+ Array,
THydratedDocumentType,
TQueryHelpers,
TRawDocType,
@@ -548,7 +551,7 @@ declare module 'mongoose' {
findByIdAndUpdate(
id: mongodb.ObjectId | any,
update: UpdateQuery,
- options: QueryOptions & { rawResult: true }
+ options: QueryOptions & { includeResultMetadata: true }
): QueryWithHelpers, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate'>;
findByIdAndUpdate(
id: mongodb.ObjectId | any,
@@ -586,12 +589,6 @@ declare module 'mongoose' {
options?: QueryOptions | null
): QueryWithHelpers;
- /** Creates a `findOneAndRemove` query: atomically finds the given document and deletes it. */
- findOneAndRemove(
- filter?: FilterQuery,
- options?: QueryOptions | null
- ): QueryWithHelpers;
-
/** Creates a `findOneAndReplace` query: atomically finds the given document and replaces it with `replacement`. */
findOneAndReplace(
filter: FilterQuery,
@@ -607,7 +604,7 @@ declare module 'mongoose' {
findOneAndReplace(
filter: FilterQuery,
replacement: TRawDocType | AnyObject,
- options: QueryOptions & { rawResult: true }
+ options: QueryOptions & { includeResultMetadata: true }
): QueryWithHelpers, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndReplace'>;
findOneAndReplace(
filter: FilterQuery,
@@ -640,7 +637,7 @@ declare module 'mongoose' {
findOneAndUpdate(
filter: FilterQuery,
update: UpdateQuery,
- options: QueryOptions & { rawResult: true }
+ options: QueryOptions & { includeResultMetadata: true }
): QueryWithHelpers, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate'>;
findOneAndUpdate(
filter: FilterQuery,
diff --git a/types/query.d.ts b/types/query.d.ts
index 3963481a20b..008f82d2d9d 100644
--- a/types/query.d.ts
+++ b/types/query.d.ts
@@ -124,9 +124,9 @@ declare module 'mongoose' {
overwriteDiscriminatorKey?: boolean;
projection?: ProjectionType;
/**
- * if true, returns the raw result from the MongoDB driver
+ * if true, returns the full ModifyResult rather than just the document
*/
- rawResult?: boolean;
+ includeResultMetadata?: boolean;
readPreference?: string | mongodb.ReadPreferenceMode;
/**
* An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
@@ -317,10 +317,10 @@ declare module 'mongoose' {
deleteOne(): QueryWithHelpers;
/** Creates a `distinct` query: returns the distinct values of the given `field` that match `filter`. */
- distinct(
- field: string,
+ distinct(
+ field: DocKey,
filter?: FilterQuery
- ): QueryWithHelpers, DocType, THelpers, RawDocType, 'distinct'>;
+ ): QueryWithHelpers, DocType, THelpers, RawDocType, 'distinct'>;
/** Specifies a `$elemMatch` query condition. When called with one argument, the most recent path passed to `where()` is used. */
elemMatch(path: K, val: any): this;
@@ -392,17 +392,11 @@ declare module 'mongoose' {
options?: QueryOptions | null
): QueryWithHelpers;
- /** Creates a `findOneAndRemove` query: atomically finds the given document and deletes it. */
- findOneAndRemove(
- filter?: FilterQuery,
- options?: QueryOptions | null
- ): QueryWithHelpers;
-
/** Creates a `findOneAndUpdate` query: atomically find the first document that matches `filter` and apply `update`. */
findOneAndUpdate(
filter: FilterQuery,
update: UpdateQuery,
- options: QueryOptions & { rawResult: true }
+ options: QueryOptions & { includeResultMetadata: true }
): QueryWithHelpers, DocType, THelpers, RawDocType, 'findOneAndUpdate'>;
findOneAndUpdate(
filter: FilterQuery,
@@ -439,7 +433,7 @@ declare module 'mongoose' {
findByIdAndUpdate(
id: mongodb.ObjectId | any,
update: UpdateQuery,
- options: QueryOptions & { rawResult: true }
+ options: QueryOptions & { includeResultMetadata: true }
): QueryWithHelpers;
findByIdAndUpdate(
id: mongodb.ObjectId | any,
diff --git a/types/schematypes.d.ts b/types/schematypes.d.ts
index 5f7514a8e03..088bc27c598 100644
--- a/types/schematypes.d.ts
+++ b/types/schematypes.d.ts
@@ -39,7 +39,7 @@ declare module 'mongoose' {
type DefaultType = T extends Schema.Types.Mixed ? any : Partial>;
- class SchemaTypeOptions {
+ class SchemaTypeOptions {
type?:
T extends string ? StringSchemaDefinition :
T extends number ? NumberSchemaDefinition :
@@ -48,12 +48,12 @@ declare module 'mongoose' {
T extends Map ? SchemaDefinition :
T extends Buffer ? SchemaDefinition :
T extends Types.ObjectId ? ObjectIdSchemaDefinition :
- T extends Types.ObjectId[] ? AnyArray | AnyArray> :
- T extends object[] ? (AnyArray> | AnyArray>> | AnyArray>>) :
- T extends string[] ? AnyArray | AnyArray> :
- T extends number[] ? AnyArray | AnyArray> :
- T extends boolean[] ? AnyArray | AnyArray> :
- T extends Function[] ? AnyArray | AnyArray>> :
+ T extends Types.ObjectId[] ? AnyArray | AnyArray> :
+ T extends object[] ? (AnyArray> | AnyArray>> | AnyArray, EnforcedDocType>>) :
+ T extends string[] ? AnyArray | AnyArray> :
+ T extends number[] ? AnyArray | AnyArray> :
+ T extends boolean[] ? AnyArray | AnyArray> :
+ T extends Function[] ? AnyArray | AnyArray, EnforcedDocType>> :
T | typeof SchemaType | Schema | SchemaDefinition | Function | AnyArray;
/** Defines a virtual with the given name that gets/sets this path. */
@@ -74,13 +74,13 @@ declare module 'mongoose' {
* path cannot be set to a nullish value. If a function, Mongoose calls the
* function and only checks for nullish values if the function returns a truthy value.
*/
- required?: boolean | (() => boolean) | [boolean, string] | [() => boolean, string];
+ required?: boolean | ((this: EnforcedDocType) => boolean) | [boolean, string] | [(this: EnforcedDocType) => boolean, string];
/**
* The default value for this path. If a function, Mongoose executes the function
* and uses the return value as the default.
*/
- default?: DefaultType | ((this: any, doc: any) => DefaultType) | null;
+ default?: DefaultType | ((this: EnforcedDocType, doc: any) => DefaultType) | null;
/**
* The model that `populate()` should use if populating this path.