mongoose 5.11.13 → 5.11.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/History.md +43 -0
- package/dist/browser.umd.js +96 -92
- package/index.d.ts +48 -21
- package/lib/aggregate.js +2 -2
- package/lib/connection.js +1 -1
- package/lib/document.js +13 -16
- package/lib/error/validation.js +2 -1
- package/lib/helpers/aggregate/{stringifyAccumulatorOptions.js → stringifyFunctionOperators.js} +14 -2
- package/lib/helpers/clone.js +1 -1
- package/lib/helpers/populate/assignVals.js +1 -1
- package/lib/helpers/populate/getModelsMapForPopulate.js +5 -5
- package/lib/helpers/populate/getSchemaTypes.js +0 -7
- package/lib/helpers/query/castFilterPath.js +1 -1
- package/lib/helpers/timestamps/setupTimestamps.js +1 -1
- package/lib/helpers/update/castArrayFilters.js +1 -2
- package/lib/model.js +11 -8
- package/lib/query.js +5 -3
- package/lib/schema/SingleNestedPath.js +4 -4
- package/lib/schema/array.js +10 -3
- package/lib/schema/documentarray.js +8 -0
- package/lib/schema.js +5 -5
- package/lib/schematype.js +5 -4
- package/lib/types/core_array.js +2 -8
- package/lib/types/documentarray.js +28 -0
- package/lib/types/embedded.js +6 -5
- package/lib/types/map.js +14 -2
- package/lib/types/subdocument.js +3 -2
- package/lib/utils.js +1 -1
- package/package.json +5 -4
package/index.d.ts
CHANGED
|
@@ -546,7 +546,7 @@ declare module 'mongoose' {
|
|
|
546
546
|
populated(path: string): any;
|
|
547
547
|
|
|
548
548
|
/** Removes this document from the db. */
|
|
549
|
-
remove(options?: QueryOptions):
|
|
549
|
+
remove(options?: QueryOptions): Promise<this>;
|
|
550
550
|
remove(options?: QueryOptions, cb?: (err: CallbackError, res: any) => void): void;
|
|
551
551
|
|
|
552
552
|
/** Sends a replaceOne command with this document `_id` as the query selector. */
|
|
@@ -630,11 +630,11 @@ declare module 'mongoose' {
|
|
|
630
630
|
countDocuments(filter: FilterQuery<T>, callback?: (err: any, count: number) => void): Query<number, T>;
|
|
631
631
|
|
|
632
632
|
/** Creates a new document or documents */
|
|
633
|
-
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents): Promise<T>;
|
|
634
633
|
create<DocContents = T | DocumentDefinition<T>>(docs: DocContents[], options?: SaveOptions): Promise<T[]>;
|
|
634
|
+
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents): Promise<T>;
|
|
635
635
|
create<DocContents = T | DocumentDefinition<T>>(...docs: DocContents[]): Promise<T[]>;
|
|
636
|
-
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents, callback: (err: CallbackError, doc: T) => void): void;
|
|
637
636
|
create<DocContents = T | DocumentDefinition<T>>(docs: DocContents[], callback: (err: CallbackError, docs: T[]) => void): void;
|
|
637
|
+
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents, callback: (err: CallbackError, doc: T) => void): void;
|
|
638
638
|
|
|
639
639
|
/**
|
|
640
640
|
* Create the collection for this model. By default, if no indexes are specified,
|
|
@@ -753,6 +753,7 @@ declare module 'mongoose' {
|
|
|
753
753
|
/** Casts and validates the given object against this model's schema, passing the given `context` to custom validators. */
|
|
754
754
|
validate(callback?: (err: any) => void): Promise<void>;
|
|
755
755
|
validate(optional: any, callback?: (err: any) => void): Promise<void>;
|
|
756
|
+
validate(optional: any, pathsToValidate: string[], callback?: (err: any) => void): Promise<void>;
|
|
756
757
|
|
|
757
758
|
/** Watches the underlying collection for changes using [MongoDB change streams](https://docs.mongodb.com/manual/changeStreams/). */
|
|
758
759
|
watch(pipeline?: Array<Record<string, unknown>>, options?: mongodb.ChangeStreamOptions): mongodb.ChangeStream;
|
|
@@ -844,6 +845,8 @@ declare module 'mongoose' {
|
|
|
844
845
|
|
|
845
846
|
/** Creates a Query, applies the passed conditions, and returns the Query. */
|
|
846
847
|
where(path: string, val?: any): Query<Array<T>, T>;
|
|
848
|
+
where(obj: object): Query<Array<T>, T>;
|
|
849
|
+
where(): Query<Array<T>, T>;
|
|
847
850
|
}
|
|
848
851
|
|
|
849
852
|
interface QueryOptions {
|
|
@@ -1037,16 +1040,20 @@ declare module 'mongoose' {
|
|
|
1037
1040
|
useProjection?: boolean;
|
|
1038
1041
|
}
|
|
1039
1042
|
|
|
1043
|
+
type MongooseDocumentMiddleware = 'validate' | 'save' | 'remove' | 'updateOne' | 'deleteOne' | 'init';
|
|
1040
1044
|
type MongooseQueryMiddleware = 'count' | 'deleteMany' | 'deleteOne' | 'find' | 'findOne' | 'findOneAndDelete' | 'findOneAndRemove' | 'findOneAndUpdate' | 'remove' | 'update' | 'updateOne' | 'updateMany';
|
|
1041
1045
|
|
|
1042
|
-
|
|
1046
|
+
type SchemaPreOptions = { document?: boolean, query?: boolean };
|
|
1047
|
+
type SchemaPostOptions = { document?: boolean, query?: boolean };
|
|
1048
|
+
|
|
1049
|
+
class Schema<DocType extends Document = Document, M extends Model<DocType> = Model<DocType>, SchemaDefinitionType = undefined> extends events.EventEmitter {
|
|
1043
1050
|
/**
|
|
1044
1051
|
* Create a new schema
|
|
1045
1052
|
*/
|
|
1046
|
-
constructor(definition?: SchemaDefinition
|
|
1053
|
+
constructor(definition?: SchemaDefinition<DocumentDefinition<SchemaDefinitionType>>, options?: SchemaOptions);
|
|
1047
1054
|
|
|
1048
1055
|
/** Adds key path / schema type pairs to this schema. */
|
|
1049
|
-
add(obj: SchemaDefinition | Schema, prefix?: string): this;
|
|
1056
|
+
add(obj: SchemaDefinition<DocumentDefinition<SchemaDefinitionType>> | Schema, prefix?: string): this;
|
|
1050
1057
|
|
|
1051
1058
|
/**
|
|
1052
1059
|
* Array of child schemas (from document arrays and single nested subdocs)
|
|
@@ -1113,21 +1120,33 @@ declare module 'mongoose' {
|
|
|
1113
1120
|
plugin(fn: (schema: Schema, opts?: any) => void, opts?: any): this;
|
|
1114
1121
|
|
|
1115
1122
|
/** Defines a post hook for the model. */
|
|
1116
|
-
post<T extends Document = DocType>(method:
|
|
1117
|
-
post<T extends
|
|
1123
|
+
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: (this: T, res: any, next: (err?: CallbackError) => void) => void): this;
|
|
1124
|
+
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: (this: T, res: any, next: (err?: CallbackError) => void) => void): this;
|
|
1125
|
+
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1126
|
+
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPostOptions, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1118
1127
|
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, fn: (this: T, res: Array<any>, next: (err: CallbackError) => void) => void): this;
|
|
1128
|
+
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: (this: T, res: Array<any>, next: (err: CallbackError) => void) => void): this;
|
|
1119
1129
|
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1130
|
+
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1120
1131
|
|
|
1121
|
-
post<T extends Document = DocType>(method:
|
|
1122
|
-
post<T extends
|
|
1132
|
+
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: (this: T, err: NativeError, res: any, next: (err?: CallbackError) => void) => void): this;
|
|
1133
|
+
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: any, next: (err?: CallbackError) => void) => void): this;
|
|
1134
|
+
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1135
|
+
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1123
1136
|
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, fn: (this: T, err: NativeError, res: Array<any>, next: (err: CallbackError) => void) => void): this;
|
|
1137
|
+
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: Array<any>, next: (err: CallbackError) => void) => void): this;
|
|
1124
1138
|
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1139
|
+
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
|
|
1125
1140
|
|
|
1126
1141
|
/** Defines a pre hook for the model. */
|
|
1127
|
-
pre<T extends Document = DocType>(method:
|
|
1128
|
-
pre<T extends
|
|
1142
|
+
pre<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: (this: T, next: (err?: CallbackError) => void) => void): this;
|
|
1143
|
+
pre<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err?: CallbackError) => void) => void): this;
|
|
1144
|
+
pre<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: (this: T, next: (err: CallbackError) => void) => void): this;
|
|
1145
|
+
pre<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err: CallbackError) => void) => void): this;
|
|
1129
1146
|
pre<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, fn: (this: T, next: (err: CallbackError) => void) => void): this;
|
|
1147
|
+
pre<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err: CallbackError) => void) => void): this;
|
|
1130
1148
|
pre<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, fn: (this: T, next: (err: CallbackError) => void) => void): this;
|
|
1149
|
+
pre<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err: CallbackError) => void) => void): this;
|
|
1131
1150
|
|
|
1132
1151
|
/** Object of currently defined query helpers on this schema. */
|
|
1133
1152
|
query: any;
|
|
@@ -1163,11 +1182,17 @@ declare module 'mongoose' {
|
|
|
1163
1182
|
virtualpath(name: string): VirtualType | null;
|
|
1164
1183
|
}
|
|
1165
1184
|
|
|
1185
|
+
type SchemaDefinitionWithBuiltInClass<T> = T extends number
|
|
1186
|
+
? (typeof Number | 'number' | 'Number')
|
|
1187
|
+
: T extends string
|
|
1188
|
+
? (typeof String | 'string' | 'String')
|
|
1189
|
+
: (Function | string);
|
|
1190
|
+
|
|
1166
1191
|
type SchemaDefinitionProperty<T = undefined> = SchemaTypeOptions<T extends undefined ? any : T> |
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
Schema |
|
|
1170
|
-
Schema[] |
|
|
1192
|
+
SchemaDefinitionWithBuiltInClass<T> |
|
|
1193
|
+
typeof SchemaType |
|
|
1194
|
+
Schema<T extends Document ? T : Document<any>> |
|
|
1195
|
+
Schema<T extends Document ? T : Document<any>>[] |
|
|
1171
1196
|
SchemaTypeOptions<T extends undefined ? any : T>[] |
|
|
1172
1197
|
Function[] |
|
|
1173
1198
|
SchemaDefinition<T> |
|
|
@@ -1175,7 +1200,7 @@ declare module 'mongoose' {
|
|
|
1175
1200
|
|
|
1176
1201
|
type SchemaDefinition<T = undefined> = T extends undefined
|
|
1177
1202
|
? { [path: string]: SchemaDefinitionProperty; }
|
|
1178
|
-
: { [path in keyof T]
|
|
1203
|
+
: { [path in keyof T]?: SchemaDefinitionProperty<T[path]>; };
|
|
1179
1204
|
|
|
1180
1205
|
interface SchemaOptions {
|
|
1181
1206
|
/**
|
|
@@ -1340,7 +1365,7 @@ declare module 'mongoose' {
|
|
|
1340
1365
|
}
|
|
1341
1366
|
|
|
1342
1367
|
interface SchemaTypeOptions<T> {
|
|
1343
|
-
type?: T
|
|
1368
|
+
type?: T | SchemaDefinitionWithBuiltInClass<T>;
|
|
1344
1369
|
|
|
1345
1370
|
/** Defines a virtual with the given name that gets/sets this path. */
|
|
1346
1371
|
alias?: string;
|
|
@@ -1357,7 +1382,7 @@ declare module 'mongoose' {
|
|
|
1357
1382
|
* path cannot be set to a nullish value. If a function, Mongoose calls the
|
|
1358
1383
|
* function and only checks for nullish values if the function returns a truthy value.
|
|
1359
1384
|
*/
|
|
1360
|
-
required?: boolean | (() => boolean) | [boolean, string];
|
|
1385
|
+
required?: boolean | (() => boolean) | [boolean, string] | [() => boolean, string];
|
|
1361
1386
|
|
|
1362
1387
|
/**
|
|
1363
1388
|
* The default value for this path. If a function, Mongoose executes the function
|
|
@@ -1421,7 +1446,7 @@ declare module 'mongoose' {
|
|
|
1421
1446
|
set?: (value: T, schematype?: this) => any;
|
|
1422
1447
|
|
|
1423
1448
|
/** array of allowed values for this path. Allowed for strings, numbers, and arrays of strings */
|
|
1424
|
-
enum?: Array<string | number | null>
|
|
1449
|
+
enum?: Array<string | number | null> | { [path: string]: string | number | null };
|
|
1425
1450
|
|
|
1426
1451
|
/** The default [subtype](http://bsonspec.org/spec.html) associated with this buffer when it is stored in MongoDB. Only allowed for buffer paths */
|
|
1427
1452
|
subtype?: number
|
|
@@ -1769,7 +1794,7 @@ declare module 'mongoose' {
|
|
|
1769
1794
|
|
|
1770
1795
|
type ReturnsNewDoc = { new: true } | { returnOriginal: false };
|
|
1771
1796
|
|
|
1772
|
-
|
|
1797
|
+
class Query<ResultType, DocType extends Document> {
|
|
1773
1798
|
_mongooseOptions: MongooseQueryOptions;
|
|
1774
1799
|
|
|
1775
1800
|
/** Executes the query */
|
|
@@ -2147,6 +2172,8 @@ declare module 'mongoose' {
|
|
|
2147
2172
|
|
|
2148
2173
|
/** Specifies a path for use with chaining. */
|
|
2149
2174
|
where(path: string, val?: any): this;
|
|
2175
|
+
where(obj: object): this;
|
|
2176
|
+
where(): this;
|
|
2150
2177
|
|
|
2151
2178
|
/** Defines a `$within` or `$geoWithin` argument for geo-spatial queries. */
|
|
2152
2179
|
within(val?: any): this;
|
package/lib/aggregate.js
CHANGED
|
@@ -8,7 +8,7 @@ const AggregationCursor = require('./cursor/AggregationCursor');
|
|
|
8
8
|
const Query = require('./query');
|
|
9
9
|
const applyGlobalMaxTimeMS = require('./helpers/query/applyGlobalMaxTimeMS');
|
|
10
10
|
const promiseOrCallback = require('./helpers/promiseOrCallback');
|
|
11
|
-
const
|
|
11
|
+
const stringifyFunctionOperators = require('./helpers/aggregate/stringifyFunctionOperators');
|
|
12
12
|
const util = require('util');
|
|
13
13
|
const utils = require('./utils');
|
|
14
14
|
const read = Query.prototype.read;
|
|
@@ -983,7 +983,7 @@ Aggregate.prototype.exec = function(callback) {
|
|
|
983
983
|
|
|
984
984
|
return promiseOrCallback(callback, cb => {
|
|
985
985
|
prepareDiscriminatorPipeline(this);
|
|
986
|
-
|
|
986
|
+
stringifyFunctionOperators(this._pipeline);
|
|
987
987
|
|
|
988
988
|
model.hooks.execPre('aggregate', this, error => {
|
|
989
989
|
if (error) {
|
package/lib/connection.js
CHANGED
|
@@ -469,7 +469,7 @@ Connection.prototype.startSession = _wrapConnHelper(function startSession(option
|
|
|
469
469
|
* @method transaction
|
|
470
470
|
* @param {Function} fn Function to execute in a transaction
|
|
471
471
|
* @param {mongodb.TransactionOptions} [options] Optional settings for the transaction
|
|
472
|
-
* @return {Promise<Any>} promise that
|
|
472
|
+
* @return {Promise<Any>} promise that is fulfilled if Mongoose successfully committed the transaction, or rejects if the transaction was aborted or if Mongoose failed to commit the transaction. If fulfilled, the promise resolves to a MongoDB command result.
|
|
473
473
|
* @api public
|
|
474
474
|
*/
|
|
475
475
|
|
package/lib/document.js
CHANGED
|
@@ -41,7 +41,6 @@ const isMongooseObject = utils.isMongooseObject;
|
|
|
41
41
|
const arrayAtomicsBackupSymbol = Symbol('mongoose.Array#atomicsBackup');
|
|
42
42
|
const arrayAtomicsSymbol = require('./helpers/symbols').arrayAtomicsSymbol;
|
|
43
43
|
const documentArrayParent = require('./helpers/symbols').documentArrayParent;
|
|
44
|
-
const documentIsSelected = require('./helpers/symbols').documentIsSelected;
|
|
45
44
|
const documentIsModified = require('./helpers/symbols').documentIsModified;
|
|
46
45
|
const documentModifiedPaths = require('./helpers/symbols').documentModifiedPaths;
|
|
47
46
|
const documentSchemaSymbol = require('./helpers/symbols').documentSchemaSymbol;
|
|
@@ -141,7 +140,6 @@ function Document(obj, fields, skipId, options) {
|
|
|
141
140
|
});
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
|
-
|
|
145
143
|
if (obj) {
|
|
146
144
|
// Skip set hooks
|
|
147
145
|
if (this.$__original_set) {
|
|
@@ -665,7 +663,7 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
665
663
|
// Should still work if not a model-level discriminator, but should not be
|
|
666
664
|
// necessary. This is *only* to catch the case where we queried using the
|
|
667
665
|
// base model and the discriminated model has a projection
|
|
668
|
-
if (self.schema.$isRootDiscriminator && !self
|
|
666
|
+
if (self.schema.$isRootDiscriminator && !self.$__isSelected(path)) {
|
|
669
667
|
return;
|
|
670
668
|
}
|
|
671
669
|
|
|
@@ -900,6 +898,7 @@ Document.prototype.overwrite = function overwrite(obj) {
|
|
|
900
898
|
*/
|
|
901
899
|
|
|
902
900
|
Document.prototype.$set = function $set(path, val, type, options) {
|
|
901
|
+
|
|
903
902
|
if (utils.isPOJO(type)) {
|
|
904
903
|
options = type;
|
|
905
904
|
type = undefined;
|
|
@@ -938,9 +937,13 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
938
937
|
path = path._doc;
|
|
939
938
|
}
|
|
940
939
|
}
|
|
940
|
+
if (path == null) {
|
|
941
|
+
const _ = path;
|
|
942
|
+
path = val;
|
|
943
|
+
val = _;
|
|
944
|
+
}
|
|
941
945
|
|
|
942
946
|
prefix = val ? val + '.' : '';
|
|
943
|
-
|
|
944
947
|
keys = Object.keys(path);
|
|
945
948
|
const len = keys.length;
|
|
946
949
|
|
|
@@ -1140,7 +1143,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1140
1143
|
// traverse the element ({nested: null})` is not likely. If user gets
|
|
1141
1144
|
// that error, its their fault for now. We should reconsider disallowing
|
|
1142
1145
|
// modifying not selected paths for 6.x
|
|
1143
|
-
if (!this
|
|
1146
|
+
if (!this.$__isSelected(curPath)) {
|
|
1144
1147
|
this.unmarkModified(curPath);
|
|
1145
1148
|
}
|
|
1146
1149
|
cur = this.$__getValue(curPath);
|
|
@@ -1421,7 +1424,7 @@ Document.prototype.$__shouldModify = function(pathToMark, path, constructing, pa
|
|
|
1421
1424
|
return false;
|
|
1422
1425
|
}
|
|
1423
1426
|
|
|
1424
|
-
if (val === void 0 && !this
|
|
1427
|
+
if (val === void 0 && !this.$__isSelected(path)) {
|
|
1425
1428
|
// when a path is not selected in a query, its initial
|
|
1426
1429
|
// value will be undefined.
|
|
1427
1430
|
return true;
|
|
@@ -2062,7 +2065,7 @@ Document.prototype.isSelected = function isSelected(path) {
|
|
|
2062
2065
|
path = path.split(' ');
|
|
2063
2066
|
}
|
|
2064
2067
|
if (Array.isArray(path)) {
|
|
2065
|
-
return path.some(p => this
|
|
2068
|
+
return path.some(p => this.$__isSelected(p));
|
|
2066
2069
|
}
|
|
2067
2070
|
|
|
2068
2071
|
const paths = Object.keys(this.$__.selected);
|
|
@@ -2111,7 +2114,7 @@ Document.prototype.isSelected = function isSelected(path) {
|
|
|
2111
2114
|
return !inclusive;
|
|
2112
2115
|
};
|
|
2113
2116
|
|
|
2114
|
-
Document.prototype
|
|
2117
|
+
Document.prototype.$__isSelected = Document.prototype.isSelected;
|
|
2115
2118
|
|
|
2116
2119
|
/**
|
|
2117
2120
|
* Checks if `path` was explicitly selected. If no projection, always returns
|
|
@@ -2257,10 +2260,9 @@ function _getPathsToValidate(doc) {
|
|
|
2257
2260
|
const skipSchemaValidators = {};
|
|
2258
2261
|
|
|
2259
2262
|
_evaluateRequiredFunctions(doc);
|
|
2260
|
-
|
|
2261
2263
|
// only validate required fields when necessary
|
|
2262
2264
|
let paths = new Set(Object.keys(doc.$__.activePaths.states.require).filter(function(path) {
|
|
2263
|
-
if (!doc
|
|
2265
|
+
if (!doc.$__isSelected(path) && !doc.isModified(path)) {
|
|
2264
2266
|
return false;
|
|
2265
2267
|
}
|
|
2266
2268
|
if (path in doc.$__.cachedRequired) {
|
|
@@ -2341,7 +2343,6 @@ function _getPathsToValidate(doc) {
|
|
|
2341
2343
|
}
|
|
2342
2344
|
}
|
|
2343
2345
|
|
|
2344
|
-
|
|
2345
2346
|
for (const path of paths) {
|
|
2346
2347
|
// Single nested paths (paths embedded under single nested subdocs) will
|
|
2347
2348
|
// be validated on their own when we call `validate()` on the subdoc itself.
|
|
@@ -2435,11 +2436,9 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
|
|
|
2435
2436
|
pathDetails[0].filter((path) => this.isModified(path)) :
|
|
2436
2437
|
pathDetails[0];
|
|
2437
2438
|
const skipSchemaValidators = pathDetails[1];
|
|
2438
|
-
|
|
2439
2439
|
if (Array.isArray(pathsToValidate)) {
|
|
2440
2440
|
paths = _handlePathsToValidate(paths, pathsToValidate);
|
|
2441
2441
|
}
|
|
2442
|
-
|
|
2443
2442
|
if (paths.length === 0) {
|
|
2444
2443
|
return process.nextTick(function() {
|
|
2445
2444
|
const error = _complete();
|
|
@@ -2607,7 +2606,6 @@ Document.prototype.validateSync = function(pathsToValidate, options) {
|
|
|
2607
2606
|
if (Array.isArray(pathsToValidate)) {
|
|
2608
2607
|
paths = _handlePathsToValidate(paths, pathsToValidate);
|
|
2609
2608
|
}
|
|
2610
|
-
|
|
2611
2609
|
const validating = {};
|
|
2612
2610
|
|
|
2613
2611
|
paths.forEach(function(path) {
|
|
@@ -3569,7 +3567,7 @@ function applyGetters(self, json, options) {
|
|
|
3569
3567
|
let part;
|
|
3570
3568
|
cur = self._doc;
|
|
3571
3569
|
|
|
3572
|
-
if (!self
|
|
3570
|
+
if (!self.$__isSelected(path)) {
|
|
3573
3571
|
continue;
|
|
3574
3572
|
}
|
|
3575
3573
|
|
|
@@ -4135,7 +4133,6 @@ Document.prototype.$__fullPath = function(path) {
|
|
|
4135
4133
|
|
|
4136
4134
|
Document.prototype.getChanges = function() {
|
|
4137
4135
|
const delta = this.$__delta();
|
|
4138
|
-
|
|
4139
4136
|
const changes = delta ? delta[1] : {};
|
|
4140
4137
|
return changes;
|
|
4141
4138
|
};
|
package/lib/error/validation.js
CHANGED
|
@@ -67,13 +67,14 @@ if (util.inspect.custom) {
|
|
|
67
67
|
|
|
68
68
|
/*!
|
|
69
69
|
* Helper for JSON.stringify
|
|
70
|
+
* Ensure `name` and `message` show up in toJSON output re: gh-9847
|
|
70
71
|
*/
|
|
71
72
|
Object.defineProperty(ValidationError.prototype, 'toJSON', {
|
|
72
73
|
enumerable: false,
|
|
73
74
|
writable: false,
|
|
74
75
|
configurable: true,
|
|
75
76
|
value: function() {
|
|
76
|
-
return Object.assign({}, this, { message: this.message });
|
|
77
|
+
return Object.assign({}, this, { name: this.name, message: this.message });
|
|
77
78
|
}
|
|
78
79
|
});
|
|
79
80
|
|
package/lib/helpers/aggregate/{stringifyAccumulatorOptions.js → stringifyFunctionOperators.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
module.exports = function
|
|
3
|
+
module.exports = function stringifyFunctionOperators(pipeline) {
|
|
4
4
|
if (!Array.isArray(pipeline)) {
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
@@ -17,9 +17,21 @@ module.exports = function stringifyAccumulatorOptions(pipeline) {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
const stageType = Object.keys(stage)[0];
|
|
21
|
+
if (stageType && typeof stage[stageType] === 'object') {
|
|
22
|
+
const stageOptions = stage[stageType];
|
|
23
|
+
for (const key of Object.keys(stageOptions)) {
|
|
24
|
+
if (stageOptions[key] != null &&
|
|
25
|
+
stageOptions[key].$function != null &&
|
|
26
|
+
typeof stageOptions[key].$function.body === 'function') {
|
|
27
|
+
stageOptions[key].$function.body = stageOptions[key].$function.body.toString();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
if (stage.$facet != null) {
|
|
21
33
|
for (const key of Object.keys(stage.$facet)) {
|
|
22
|
-
|
|
34
|
+
stringifyFunctionOperators(stage.$facet[key]);
|
|
23
35
|
}
|
|
24
36
|
}
|
|
25
37
|
}
|
package/lib/helpers/clone.js
CHANGED
|
@@ -43,7 +43,6 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
43
43
|
for (i = 0; i < len; i++) {
|
|
44
44
|
doc = docs[i];
|
|
45
45
|
let justOne = null;
|
|
46
|
-
|
|
47
46
|
schema = getSchemaTypes(modelSchema, doc, options.path);
|
|
48
47
|
// Special case: populating a path that's a DocumentArray unless
|
|
49
48
|
// there's an explicit `ref` or `refPath` re: gh-8946
|
|
@@ -174,9 +173,11 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
174
173
|
}
|
|
175
174
|
} else if (schema && !schema[schemaMixedSymbol]) {
|
|
176
175
|
// Skip Mixed types because we explicitly don't do casting on those.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
if (options.path.endsWith('.' + schema.path)) {
|
|
177
|
+
justOne = Array.isArray(schema) ?
|
|
178
|
+
schema.every(schema => !schema.$isMongooseArray) :
|
|
179
|
+
!schema.$isMongooseArray;
|
|
180
|
+
}
|
|
180
181
|
}
|
|
181
182
|
|
|
182
183
|
if (!modelNames) {
|
|
@@ -358,7 +359,6 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
|
|
358
359
|
}
|
|
359
360
|
}
|
|
360
361
|
}
|
|
361
|
-
|
|
362
362
|
return map;
|
|
363
363
|
|
|
364
364
|
function _getModelNames(doc, schema) {
|
|
@@ -20,7 +20,6 @@ const populateModelSymbol = require('../symbols').populateModelSymbol;
|
|
|
20
20
|
module.exports = function getSchemaTypes(schema, doc, path) {
|
|
21
21
|
const pathschema = schema.path(path);
|
|
22
22
|
const topLevelDoc = doc;
|
|
23
|
-
|
|
24
23
|
if (pathschema) {
|
|
25
24
|
return pathschema;
|
|
26
25
|
}
|
|
@@ -33,7 +32,6 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
|
|
33
32
|
while (p--) {
|
|
34
33
|
trypath = parts.slice(0, p).join('.');
|
|
35
34
|
foundschema = schema.path(trypath);
|
|
36
|
-
|
|
37
35
|
if (foundschema == null) {
|
|
38
36
|
continue;
|
|
39
37
|
}
|
|
@@ -117,7 +115,6 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
|
|
117
115
|
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
118
116
|
!foundschema.schema.$isSingleNested;
|
|
119
117
|
}
|
|
120
|
-
|
|
121
118
|
return ret;
|
|
122
119
|
}
|
|
123
120
|
} else if (p !== parts.length &&
|
|
@@ -153,7 +150,6 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
|
|
153
150
|
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
154
151
|
!model.schema.$isSingleNested;
|
|
155
152
|
}
|
|
156
|
-
|
|
157
153
|
return ret;
|
|
158
154
|
}
|
|
159
155
|
}
|
|
@@ -177,15 +173,12 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
|
|
177
173
|
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
|
178
174
|
!schema.$isSingleNested;
|
|
179
175
|
}
|
|
180
|
-
|
|
181
176
|
return ret;
|
|
182
177
|
}
|
|
183
178
|
}
|
|
184
|
-
|
|
185
179
|
return foundschema;
|
|
186
180
|
}
|
|
187
181
|
}
|
|
188
|
-
|
|
189
182
|
// look for arrays
|
|
190
183
|
const parts = path.split('.');
|
|
191
184
|
for (let i = 0; i < parts.length; ++i) {
|
|
@@ -25,7 +25,7 @@ module.exports = function castFilterPath(query, schematype, val) {
|
|
|
25
25
|
if (nested && schematype && !schematype.caster) {
|
|
26
26
|
const _keys = Object.keys(nested);
|
|
27
27
|
if (_keys.length && isOperator(_keys[0])) {
|
|
28
|
-
for (const key
|
|
28
|
+
for (const key of Object.keys(nested)) {
|
|
29
29
|
nested[key] = schematype.castForQueryWrapper({
|
|
30
30
|
$conditional: key,
|
|
31
31
|
val: nested[key],
|
|
@@ -51,7 +51,7 @@ module.exports = function setupTimestamps(schema, timestamps) {
|
|
|
51
51
|
(this.ownerDocument ? this.ownerDocument() : this).constructor.base.now();
|
|
52
52
|
const auto_id = this._id && this._id.auto;
|
|
53
53
|
|
|
54
|
-
if (!skipCreatedAt && createdAt && !this.get(createdAt) && this
|
|
54
|
+
if (!skipCreatedAt && createdAt && !this.get(createdAt) && this.$__isSelected(createdAt)) {
|
|
55
55
|
this.$set(createdAt, auto_id ? this._id.getTimestamp() : defaultTimestamp);
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -38,8 +38,7 @@ module.exports = function castArrayFilters(query) {
|
|
|
38
38
|
if (filter == null) {
|
|
39
39
|
throw new Error(`Got null array filter in ${arrayFilters}`);
|
|
40
40
|
}
|
|
41
|
-
for (const key
|
|
42
|
-
|
|
41
|
+
for (const key of Object.keys(filter)) {
|
|
43
42
|
if (filter[key] == null) {
|
|
44
43
|
continue;
|
|
45
44
|
}
|
package/lib/model.js
CHANGED
|
@@ -538,7 +538,6 @@ function operand(self, where, delta, data, val, op) {
|
|
|
538
538
|
op || (op = '$set');
|
|
539
539
|
if (!delta[op]) delta[op] = {};
|
|
540
540
|
delta[op][data.path] = val;
|
|
541
|
-
|
|
542
541
|
// disabled versioning?
|
|
543
542
|
if (self.schema.options.versionKey === false) return;
|
|
544
543
|
|
|
@@ -748,7 +747,6 @@ Model.prototype.$__delta = function() {
|
|
|
748
747
|
if (this.$__.version) {
|
|
749
748
|
this.$__version(where, delta);
|
|
750
749
|
}
|
|
751
|
-
|
|
752
750
|
return [where, delta];
|
|
753
751
|
};
|
|
754
752
|
|
|
@@ -825,7 +823,7 @@ Model.prototype.$__version = function(where, delta) {
|
|
|
825
823
|
// there is no way to select the correct version. we could fail
|
|
826
824
|
// fast here and force them to include the versionKey but
|
|
827
825
|
// thats a bit intrusive. can we do this automatically?
|
|
828
|
-
if (!this
|
|
826
|
+
if (!this.$__isSelected(key)) {
|
|
829
827
|
return;
|
|
830
828
|
}
|
|
831
829
|
|
|
@@ -1652,6 +1650,10 @@ function _ensureIndexes(model, options, callback) {
|
|
|
1652
1650
|
if ('background' in options) {
|
|
1653
1651
|
indexOptions.background = options.background;
|
|
1654
1652
|
}
|
|
1653
|
+
if (model.schema.options.hasOwnProperty('collation') &&
|
|
1654
|
+
!indexOptions.hasOwnProperty('collation')) {
|
|
1655
|
+
indexOptions.collation = model.schema.options.collation;
|
|
1656
|
+
}
|
|
1655
1657
|
|
|
1656
1658
|
const methodName = useCreateIndex ? 'createIndex' : 'ensureIndex';
|
|
1657
1659
|
model.collection[methodName](indexFields, indexOptions, utils.tick(function(err, name) {
|
|
@@ -4338,7 +4340,6 @@ function populate(model, docs, options, callback) {
|
|
|
4338
4340
|
}
|
|
4339
4341
|
|
|
4340
4342
|
const modelsMap = getModelsMapForPopulate(model, docs, options);
|
|
4341
|
-
|
|
4342
4343
|
if (modelsMap instanceof MongooseError) {
|
|
4343
4344
|
return immediate(function() {
|
|
4344
4345
|
callback(modelsMap);
|
|
@@ -4422,7 +4423,6 @@ function populate(model, docs, options, callback) {
|
|
|
4422
4423
|
} else if (mod.options.limit != null) {
|
|
4423
4424
|
assignmentOpts.originalLimit = mod.options.limit;
|
|
4424
4425
|
}
|
|
4425
|
-
|
|
4426
4426
|
params.push([mod, match, select, assignmentOpts, _next]);
|
|
4427
4427
|
}
|
|
4428
4428
|
|
|
@@ -4441,7 +4441,6 @@ function populate(model, docs, options, callback) {
|
|
|
4441
4441
|
for (const arr of params) {
|
|
4442
4442
|
_execPopulateQuery.apply(null, arr);
|
|
4443
4443
|
}
|
|
4444
|
-
|
|
4445
4444
|
function _next(err, valsFromDb) {
|
|
4446
4445
|
if (err != null) {
|
|
4447
4446
|
return callback(err, null);
|
|
@@ -4475,7 +4474,6 @@ function populate(model, docs, options, callback) {
|
|
|
4475
4474
|
|
|
4476
4475
|
function _execPopulateQuery(mod, match, select, assignmentOpts, callback) {
|
|
4477
4476
|
const subPopulate = utils.clone(mod.options.populate);
|
|
4478
|
-
|
|
4479
4477
|
const queryOptions = Object.assign({
|
|
4480
4478
|
skip: mod.options.skip,
|
|
4481
4479
|
limit: mod.options.limit,
|
|
@@ -4594,7 +4592,12 @@ function _assign(model, vals, mod, assignmentOpts) {
|
|
|
4594
4592
|
if (Array.isArray(rawDocs[key])) {
|
|
4595
4593
|
rawDocs[key].push(val);
|
|
4596
4594
|
rawOrder[key].push(i);
|
|
4597
|
-
} else
|
|
4595
|
+
} else if (isVirtual ||
|
|
4596
|
+
rawDocs[key].constructor !== val.constructor ||
|
|
4597
|
+
String(rawDocs[key]._id) !== String(val._id)) {
|
|
4598
|
+
// May need to store multiple docs with the same id if there's multiple models
|
|
4599
|
+
// if we have discriminators or a ref function. But avoid converting to an array
|
|
4600
|
+
// if we have multiple queries on the same model because of `perDocumentLimit` re: gh-9906
|
|
4598
4601
|
rawDocs[key] = [rawDocs[key], val];
|
|
4599
4602
|
rawOrder[key] = [rawOrder[key], i];
|
|
4600
4603
|
}
|
package/lib/query.js
CHANGED
|
@@ -1397,9 +1397,11 @@ Query.prototype.setOptions = function(options, overwrite) {
|
|
|
1397
1397
|
Query.prototype.explain = function(verbose) {
|
|
1398
1398
|
if (arguments.length === 0) {
|
|
1399
1399
|
this.options.explain = true;
|
|
1400
|
-
|
|
1400
|
+
} else if (verbose === false) {
|
|
1401
|
+
delete this.options.explain;
|
|
1402
|
+
} else {
|
|
1403
|
+
this.options.explain = verbose;
|
|
1401
1404
|
}
|
|
1402
|
-
this.options.explain = verbose;
|
|
1403
1405
|
return this;
|
|
1404
1406
|
};
|
|
1405
1407
|
|
|
@@ -4964,7 +4966,7 @@ Query.prototype.tailable = function(val, opts) {
|
|
|
4964
4966
|
}
|
|
4965
4967
|
|
|
4966
4968
|
if (opts && typeof opts === 'object') {
|
|
4967
|
-
for (const key
|
|
4969
|
+
for (const key of Object.keys(opts)) {
|
|
4968
4970
|
if (key === 'awaitdata') {
|
|
4969
4971
|
// For backwards compatibility
|
|
4970
4972
|
this.options[key] = !!opts[key];
|
|
@@ -147,7 +147,7 @@ SingleNestedPath.prototype.$conditionalHandlers.$exists = $exists;
|
|
|
147
147
|
* @api private
|
|
148
148
|
*/
|
|
149
149
|
|
|
150
|
-
SingleNestedPath.prototype.cast = function(val, doc, init, priorVal) {
|
|
150
|
+
SingleNestedPath.prototype.cast = function(val, doc, init, priorVal, options) {
|
|
151
151
|
if (val && val.$isSingleNested && val.parent === doc) {
|
|
152
152
|
return val;
|
|
153
153
|
}
|
|
@@ -169,16 +169,16 @@ SingleNestedPath.prototype.cast = function(val, doc, init, priorVal) {
|
|
|
169
169
|
}
|
|
170
170
|
return obj;
|
|
171
171
|
}, {});
|
|
172
|
-
|
|
172
|
+
options = Object.assign({}, options, { priorDoc: priorVal });
|
|
173
173
|
if (init) {
|
|
174
174
|
subdoc = new Constructor(void 0, selected, doc);
|
|
175
175
|
subdoc.init(val);
|
|
176
176
|
} else {
|
|
177
177
|
if (Object.keys(val).length === 0) {
|
|
178
|
-
return new Constructor({}, selected, doc, undefined,
|
|
178
|
+
return new Constructor({}, selected, doc, undefined, options);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
return new Constructor(val, selected, doc, undefined,
|
|
181
|
+
return new Constructor(val, selected, doc, undefined, options);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
return subdoc;
|