mongoose 6.1.2 → 6.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7036 -0
- package/History.md +1 -0
- package/dist/browser.umd.js +177 -175
- package/index.d.ts +57 -51
- package/lib/aggregate.js +1 -1
- package/lib/connection.js +9 -5
- package/lib/cursor/QueryCursor.js +1 -19
- package/lib/document.js +61 -42
- package/lib/helpers/common.js +1 -1
- package/lib/helpers/document/cleanModifiedSubpaths.js +6 -0
- package/lib/helpers/populate/getModelsMapForPopulate.js +12 -3
- package/lib/helpers/populate/modelNamesFromRefPath.js +4 -2
- package/lib/helpers/query/castUpdate.js +2 -2
- package/lib/helpers/timestamps/setupTimestamps.js +1 -1
- package/lib/index.js +10 -1
- package/lib/internal.js +3 -5
- package/lib/model.js +16 -3
- package/lib/plugins/clearValidating.js +2 -2
- package/lib/plugins/removeSubdocs.js +1 -1
- package/lib/plugins/saveSubdocs.js +2 -2
- package/lib/plugins/validateBeforeSave.js +1 -1
- package/lib/query.js +46 -1
- package/lib/queryhelpers.js +8 -8
- package/lib/schema/SubdocumentPath.js +4 -3
- package/lib/schema/boolean.js +1 -4
- package/lib/schema/buffer.js +3 -1
- package/lib/schema/documentarray.js +2 -2
- package/lib/schema/number.js +3 -1
- package/lib/schema/objectid.js +3 -1
- package/lib/schema.js +10 -4
- package/lib/schematype.js +1 -1
- package/lib/types/ArraySubdocument.js +1 -2
- package/lib/types/DocumentArray/methods/index.js +6 -6
- package/lib/types/subdocument.js +11 -3
- package/package.json +10 -9
package/index.d.ts
CHANGED
|
@@ -77,6 +77,10 @@ declare module 'mongoose' {
|
|
|
77
77
|
export function syncIndexes(options?: Record<string, unknown>): Promise<Array<string>>;
|
|
78
78
|
export function syncIndexes(options: Record<string, unknown> | null, callback: Callback<Array<string>>): void;
|
|
79
79
|
|
|
80
|
+
/* Tells `sanitizeFilter()` to skip the given object when filtering out potential query selector injection attacks.
|
|
81
|
+
* Use this method when you have a known query selector that you want to use. */
|
|
82
|
+
export function trusted<T>(obj: T): T;
|
|
83
|
+
|
|
80
84
|
/** The Mongoose module's default connection. Equivalent to `mongoose.connections[0]`, see [`connections`](#mongoose_Mongoose-connections). */
|
|
81
85
|
export const connection: Connection;
|
|
82
86
|
|
|
@@ -763,7 +767,7 @@ declare module 'mongoose' {
|
|
|
763
767
|
|
|
764
768
|
export const Model: Model<any>;
|
|
765
769
|
interface Model<T, TQueryHelpers = {}, TMethods = {}, TVirtuals = {}> extends NodeJS.EventEmitter, AcceptsDiscriminator {
|
|
766
|
-
new
|
|
770
|
+
new<DocType = AnyKeys<T> & AnyObject>(doc?: DocType, fields?: any | null, options?: boolean | AnyObject): HydratedDocument<T, TMethods, TVirtuals>;
|
|
767
771
|
|
|
768
772
|
aggregate<R = any>(pipeline?: PipelineStage[], options?: mongodb.AggregateOptions, callback?: Callback<R[]>): Aggregate<Array<R>>;
|
|
769
773
|
aggregate<R = any>(pipeline: PipelineStage[], cb: Function): Aggregate<Array<R>>;
|
|
@@ -1217,7 +1221,7 @@ declare module 'mongoose' {
|
|
|
1217
1221
|
/** optional query options like sort, limit, etc */
|
|
1218
1222
|
options?: any;
|
|
1219
1223
|
/** deep populate */
|
|
1220
|
-
populate?: PopulateOptions |
|
|
1224
|
+
populate?: string | PopulateOptions | (string | PopulateOptions)[];
|
|
1221
1225
|
/**
|
|
1222
1226
|
* If true Mongoose will always set `path` to an array, if false Mongoose will
|
|
1223
1227
|
* always set `path` to a document. Inferred from schema by default.
|
|
@@ -1254,7 +1258,6 @@ declare module 'mongoose' {
|
|
|
1254
1258
|
type SchemaPreOptions = { document?: boolean, query?: boolean };
|
|
1255
1259
|
type SchemaPostOptions = { document?: boolean, query?: boolean };
|
|
1256
1260
|
|
|
1257
|
-
type ExtractQueryHelpers<M> = M extends Model<any, infer TQueryHelpers, any, any> ? TQueryHelpers : {};
|
|
1258
1261
|
type ExtractVirtuals<M> = M extends Model<any, any, any, infer TVirtuals> ? TVirtuals : {};
|
|
1259
1262
|
|
|
1260
1263
|
type IndexDirection = 1 | -1 | '2d' | '2dsphere' | 'geoHaystack' | 'hashed' | 'text';
|
|
@@ -1265,7 +1268,7 @@ declare module 'mongoose' {
|
|
|
1265
1268
|
type PostMiddlewareFunction<ThisType, ResType = any> = (this: ThisType, res: ResType, next: (err?: CallbackError) => void) => void | Promise<void>;
|
|
1266
1269
|
type ErrorHandlingMiddlewareFunction<ThisType, ResType = any> = (this: ThisType, err: NativeError, res: ResType, next: (err?: CallbackError) => void) => void;
|
|
1267
1270
|
|
|
1268
|
-
class Schema<DocType = any, M = Model<DocType, any, any, any>, TInstanceMethods = any> extends events.EventEmitter {
|
|
1271
|
+
class Schema<DocType = any, M = Model<DocType, any, any, any>, TInstanceMethods = any, TQueryHelpers = any> extends events.EventEmitter {
|
|
1269
1272
|
/**
|
|
1270
1273
|
* Create a new schema
|
|
1271
1274
|
*/
|
|
@@ -1312,11 +1315,11 @@ declare module 'mongoose' {
|
|
|
1312
1315
|
loadClass(model: Function, onlyVirtuals?: boolean): this;
|
|
1313
1316
|
|
|
1314
1317
|
/** Adds an instance method to documents constructed from Models compiled from this schema. */
|
|
1315
|
-
method(name: string, fn: (this:
|
|
1316
|
-
method(obj:
|
|
1318
|
+
method<Context = any>(name: string, fn: (this: Context, ...args: any[]) => any, opts?: any): this;
|
|
1319
|
+
method(obj: Partial<TInstanceMethods>): this;
|
|
1317
1320
|
|
|
1318
1321
|
/** Object of currently defined methods on this schema. */
|
|
1319
|
-
methods: { [
|
|
1322
|
+
methods: { [F in keyof TInstanceMethods]: TInstanceMethods[F] };
|
|
1320
1323
|
|
|
1321
1324
|
/** The original object passed to the schema constructor */
|
|
1322
1325
|
obj: SchemaDefinition<SchemaDefinitionType<DocType>>;
|
|
@@ -1328,7 +1331,7 @@ declare module 'mongoose' {
|
|
|
1328
1331
|
/** Lists all paths and their type in the schema. */
|
|
1329
1332
|
paths: {
|
|
1330
1333
|
[key: string]: SchemaType;
|
|
1331
|
-
}
|
|
1334
|
+
};
|
|
1332
1335
|
|
|
1333
1336
|
/** Returns the pathType of `path` for this schema. */
|
|
1334
1337
|
pathType(path: string): string;
|
|
@@ -1337,37 +1340,37 @@ declare module 'mongoose' {
|
|
|
1337
1340
|
plugin(fn: (schema: Schema<DocType>, opts?: any) => void, opts?: any): this;
|
|
1338
1341
|
|
|
1339
1342
|
/** Defines a post hook for the model. */
|
|
1340
|
-
post<T = HydratedDocument<DocType, TInstanceMethods
|
|
1341
|
-
post<T = HydratedDocument<DocType, TInstanceMethods
|
|
1342
|
-
post<T extends Query<any, any
|
|
1343
|
-
post<T extends Query<any, any
|
|
1344
|
-
post<T extends Aggregate<any
|
|
1345
|
-
post<T extends Aggregate<any
|
|
1343
|
+
post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PostMiddlewareFunction<T>): this;
|
|
1344
|
+
post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T>): this;
|
|
1345
|
+
post<T extends Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: PostMiddlewareFunction<T>): this;
|
|
1346
|
+
post<T extends Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T>): this;
|
|
1347
|
+
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PostMiddlewareFunction<T, Array<any>>): this;
|
|
1348
|
+
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, Array<any>>): this;
|
|
1346
1349
|
post<T = M>(method: 'insertMany' | RegExp, fn: PostMiddlewareFunction<T>): this;
|
|
1347
1350
|
post<T = M>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T>): this;
|
|
1348
1351
|
|
|
1349
|
-
post<T = HydratedDocument<DocType, TInstanceMethods
|
|
1350
|
-
post<T = HydratedDocument<DocType, TInstanceMethods
|
|
1351
|
-
post<T extends Query<any, any
|
|
1352
|
-
post<T extends Query<any, any
|
|
1353
|
-
post<T extends Aggregate<any
|
|
1354
|
-
post<T extends Aggregate<any
|
|
1352
|
+
post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
1353
|
+
post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
1354
|
+
post<T extends Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
1355
|
+
post<T extends Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
1356
|
+
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: ErrorHandlingMiddlewareFunction<T, Array<any>>): this;
|
|
1357
|
+
post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T, Array<any>>): this;
|
|
1355
1358
|
post<T = M>(method: 'insertMany' | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
1356
1359
|
post<T = M>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T>): this;
|
|
1357
1360
|
|
|
1358
1361
|
/** Defines a pre hook for the model. */
|
|
1359
|
-
pre<T = HydratedDocument<DocType, TInstanceMethods
|
|
1360
|
-
pre<T = HydratedDocument<DocType, TInstanceMethods
|
|
1361
|
-
pre<T
|
|
1362
|
-
pre<T extends Query<any, any
|
|
1363
|
-
pre<T extends Query<any, any
|
|
1364
|
-
pre<T extends Aggregate<any
|
|
1365
|
-
pre<T extends Aggregate<any
|
|
1362
|
+
pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: 'save', fn: PreSaveMiddlewareFunction<T>): this;
|
|
1363
|
+
pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
|
|
1364
|
+
pre<T extends Query<any, any>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
|
|
1365
|
+
pre<T extends Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: PreMiddlewareFunction<T>): this;
|
|
1366
|
+
pre<T extends Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
|
|
1367
|
+
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PreMiddlewareFunction<T>): this;
|
|
1368
|
+
pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
|
|
1366
1369
|
pre<T = M>(method: 'insertMany' | RegExp, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
|
|
1367
1370
|
pre<T = M>(method: 'insertMany' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
|
|
1368
1371
|
|
|
1369
1372
|
/** Object of currently defined query helpers on this schema. */
|
|
1370
|
-
query:
|
|
1373
|
+
query: TQueryHelpers;
|
|
1371
1374
|
|
|
1372
1375
|
/** Adds a method call to the queue. */
|
|
1373
1376
|
queue(name: string, args: any[]): this;
|
|
@@ -1624,7 +1627,7 @@ declare module 'mongoose' {
|
|
|
1624
1627
|
* The default value for this path. If a function, Mongoose executes the function
|
|
1625
1628
|
* and uses the return value as the default.
|
|
1626
1629
|
*/
|
|
1627
|
-
default?: T | ((this: any, doc: any) => T);
|
|
1630
|
+
default?: T | ((this: any, doc: any) => Partial<T>);
|
|
1628
1631
|
|
|
1629
1632
|
/**
|
|
1630
1633
|
* The model that `populate()` should use if populating this path.
|
|
@@ -1685,7 +1688,7 @@ declare module 'mongoose' {
|
|
|
1685
1688
|
enum?: Array<string | number | null> | ReadonlyArray<string | number | null> | { values: Array<string | number | null> | ReadonlyArray<string | number | null>, message?: string } | { [path: string]: string | number | null };
|
|
1686
1689
|
|
|
1687
1690
|
/** The default [subtype](http://bsonspec.org/spec.html) associated with this buffer when it is stored in MongoDB. Only allowed for buffer paths */
|
|
1688
|
-
subtype?: number
|
|
1691
|
+
subtype?: number;
|
|
1689
1692
|
|
|
1690
1693
|
/** The minimum value allowed for this path. Only allowed for numbers and dates. */
|
|
1691
1694
|
min?: number | NativeDate | [number, string] | [NativeDate, string] | readonly [number, string] | readonly [NativeDate, string];
|
|
@@ -2094,7 +2097,7 @@ declare module 'mongoose' {
|
|
|
2094
2097
|
_id: this;
|
|
2095
2098
|
}
|
|
2096
2099
|
|
|
2097
|
-
class Subdocument extends Document {
|
|
2100
|
+
class Subdocument<IdType = any> extends Document<IdType> {
|
|
2098
2101
|
$isSingleNested: true;
|
|
2099
2102
|
|
|
2100
2103
|
/** Returns the top level document of this sub-document. */
|
|
@@ -2112,6 +2115,8 @@ declare module 'mongoose' {
|
|
|
2112
2115
|
|
|
2113
2116
|
type QueryWithHelpers<ResultType, DocType, THelpers = {}, RawDocType = DocType> = Query<ResultType, DocType, THelpers, RawDocType> & THelpers;
|
|
2114
2117
|
|
|
2118
|
+
type UnpackedIntersection<T, U> = T extends (infer V)[] ? (V & U)[] : T & U;
|
|
2119
|
+
|
|
2115
2120
|
class Query<ResultType, DocType, THelpers = {}, RawDocType = DocType> {
|
|
2116
2121
|
_mongooseOptions: MongooseQueryOptions;
|
|
2117
2122
|
|
|
@@ -2315,7 +2320,7 @@ declare module 'mongoose' {
|
|
|
2315
2320
|
j(val: boolean | null): this;
|
|
2316
2321
|
|
|
2317
2322
|
/** Sets the lean option. */
|
|
2318
|
-
lean<LeanResultType = RawDocType extends Document ? LeanDocumentOrArray<ResultType> : LeanDocumentOrArrayWithRawType<ResultType, RawDocType
|
|
2323
|
+
lean<LeanResultType = RawDocType extends Document ? LeanDocumentOrArray<ResultType> : LeanDocumentOrArrayWithRawType<ResultType, Require_id<RawDocType>>>(val?: boolean | any): QueryWithHelpers<LeanResultType, DocType, THelpers, RawDocType>;
|
|
2319
2324
|
|
|
2320
2325
|
/** Specifies the maximum number of documents the query will return. */
|
|
2321
2326
|
limit(val: number): this;
|
|
@@ -2332,7 +2337,7 @@ declare module 'mongoose' {
|
|
|
2332
2337
|
* Runs a function `fn` and treats the return value of `fn` as the new value
|
|
2333
2338
|
* for the query to resolve to.
|
|
2334
2339
|
*/
|
|
2335
|
-
|
|
2340
|
+
transform<MappedType>(fn: (doc: ResultType) => MappedType): QueryWithHelpers<MappedType, DocType, THelpers, RawDocType>;
|
|
2336
2341
|
|
|
2337
2342
|
/** Specifies an `$maxDistance` query condition. When called with one argument, the most recent path passed to `where()` is used. */
|
|
2338
2343
|
maxDistance(val: number): this;
|
|
@@ -2394,11 +2399,11 @@ declare module 'mongoose' {
|
|
|
2394
2399
|
polygon(path: string, ...coordinatePairs: number[][]): this;
|
|
2395
2400
|
|
|
2396
2401
|
/** Specifies paths which should be populated with other documents. */
|
|
2397
|
-
populate<Paths = {}>(path: string | any, select?: string | any, model?: string | Model<any, THelpers>, match?: any): QueryWithHelpers<ResultType
|
|
2398
|
-
populate<Paths = {}>(options: PopulateOptions | Array<PopulateOptions>): QueryWithHelpers<ResultType
|
|
2402
|
+
populate<Paths = {}>(path: string | any, select?: string | any, model?: string | Model<any, THelpers>, match?: any): QueryWithHelpers<UnpackedIntersection<ResultType, Paths>, DocType, THelpers, RawDocType>;
|
|
2403
|
+
populate<Paths = {}>(options: PopulateOptions | Array<PopulateOptions>): QueryWithHelpers<UnpackedIntersection<ResultType, Paths>, DocType, THelpers, RawDocType>;
|
|
2399
2404
|
|
|
2400
2405
|
/** Get/set the current projection (AKA fields). Pass `null` to remove the current projection. */
|
|
2401
|
-
projection(fields?: any | null):
|
|
2406
|
+
projection(fields?: any | null): this;
|
|
2402
2407
|
|
|
2403
2408
|
/** Determines the MongoDB nodes from which to read. */
|
|
2404
2409
|
read(pref: string | mongodb.ReadPreferenceMode, tags?: any[]): this;
|
|
@@ -2674,7 +2679,9 @@ declare module 'mongoose' {
|
|
|
2674
2679
|
};
|
|
2675
2680
|
|
|
2676
2681
|
export type FlattenMaps<T> = {
|
|
2677
|
-
[K in keyof T]: T[K] extends Map<any, any>
|
|
2682
|
+
[K in keyof T]: T[K] extends Map<any, any>
|
|
2683
|
+
? AnyObject : T[K] extends TreatAsPrimitives
|
|
2684
|
+
? T[K] : FlattenMaps<T[K]>;
|
|
2678
2685
|
};
|
|
2679
2686
|
|
|
2680
2687
|
type actualPrimitives = string | boolean | number | bigint | symbol | null | undefined;
|
|
@@ -2704,10 +2711,6 @@ declare module 'mongoose' {
|
|
|
2704
2711
|
export type SchemaDefinitionType<T> = T extends Document ? Omit<T, Exclude<keyof Document, '_id' | 'id' | '__v'>> : T;
|
|
2705
2712
|
export type LeanDocument<T> = Omit<_LeanDocument<T>, Exclude<keyof Document, '_id' | 'id' | '__v'> | '$isSingleNested'>;
|
|
2706
2713
|
|
|
2707
|
-
type DeepPartial<T> = {
|
|
2708
|
-
[K in keyof T]?: DeepPartial<T[K]>;
|
|
2709
|
-
}
|
|
2710
|
-
|
|
2711
2714
|
export type LeanDocumentOrArray<T> = 0 extends (1 & T) ? T :
|
|
2712
2715
|
T extends unknown[] ? LeanDocument<T[number]>[] :
|
|
2713
2716
|
T extends Document ? LeanDocument<T> :
|
|
@@ -2762,6 +2765,13 @@ declare module 'mongoose' {
|
|
|
2762
2765
|
}
|
|
2763
2766
|
|
|
2764
2767
|
class Aggregate<R> {
|
|
2768
|
+
/**
|
|
2769
|
+
* Returns an asyncIterator for use with [`for/await/of` loops](https://thecodebarbarian.com/getting-started-with-async-iterators-in-node-js
|
|
2770
|
+
* You do not need to call this function explicitly, the JavaScript runtime
|
|
2771
|
+
* will call it for you.
|
|
2772
|
+
*/
|
|
2773
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<Unpacked<R>>;
|
|
2774
|
+
|
|
2765
2775
|
/**
|
|
2766
2776
|
* Sets an option on this aggregation. This function will be deprecated in a
|
|
2767
2777
|
* future release. */
|
|
@@ -3016,12 +3026,11 @@ declare module 'mongoose' {
|
|
|
3016
3026
|
|
|
3017
3027
|
export interface Facet {
|
|
3018
3028
|
/** [`$facet` reference](https://docs.mongodb.com/manual/reference/operator/aggregation/facet/) */
|
|
3019
|
-
$facet: Record<
|
|
3020
|
-
string,
|
|
3021
|
-
Exclude<PipelineStage, PipelineStage.CollStats | PipelineStage.Facet | PipelineStage.GeoNear | PipelineStage.IndexStats | PipelineStage.Out | PipelineStage.Merge | PipelineStage.PlanCacheStats>[]
|
|
3022
|
-
>
|
|
3029
|
+
$facet: Record<string, FacetPipelineStage[]>
|
|
3023
3030
|
}
|
|
3024
3031
|
|
|
3032
|
+
export type FacetPipelineStage = Exclude<PipelineStage, PipelineStage.CollStats | PipelineStage.Facet | PipelineStage.GeoNear | PipelineStage.IndexStats | PipelineStage.Out | PipelineStage.Merge | PipelineStage.PlanCacheStats>
|
|
3033
|
+
|
|
3025
3034
|
export interface GeoNear {
|
|
3026
3035
|
/** [`$geoNear` reference](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/) */
|
|
3027
3036
|
$geoNear: {
|
|
@@ -3054,10 +3063,7 @@ declare module 'mongoose' {
|
|
|
3054
3063
|
|
|
3055
3064
|
export interface Group {
|
|
3056
3065
|
/** [`$group` reference](https://docs.mongodb.com/manual/reference/operator/aggregation/group) */
|
|
3057
|
-
$group: {
|
|
3058
|
-
_id: any
|
|
3059
|
-
[key: string]: { [op in AccumulatorOperator]?: any }
|
|
3060
|
-
}
|
|
3066
|
+
$group: { _id: any } | { [key: string]: { [op in AccumulatorOperator]?: any } }
|
|
3061
3067
|
}
|
|
3062
3068
|
|
|
3063
3069
|
export interface IndexStats {
|
|
@@ -3098,7 +3104,7 @@ declare module 'mongoose' {
|
|
|
3098
3104
|
into: string | { db: string; coll: string }
|
|
3099
3105
|
on?: string | string[]
|
|
3100
3106
|
let?: Record<string, any>
|
|
3101
|
-
whenMatched?: 'replace' | 'keepExisting' | 'merge' | 'fail' |
|
|
3107
|
+
whenMatched?: 'replace' | 'keepExisting' | 'merge' | 'fail' | Extract<PipelineStage, PipelineStage.AddFields | PipelineStage.Set | PipelineStage.Project | PipelineStage.Unset | PipelineStage.ReplaceRoot | PipelineStage.ReplaceWith>[]
|
|
3102
3108
|
whenNotMatched?: 'insert' | 'discard' | 'fail'
|
|
3103
3109
|
}
|
|
3104
3110
|
}
|
|
@@ -3115,7 +3121,7 @@ declare module 'mongoose' {
|
|
|
3115
3121
|
|
|
3116
3122
|
export interface Project {
|
|
3117
3123
|
/** [`$project` reference](https://docs.mongodb.com/manual/reference/operator/aggregation/project/) */
|
|
3118
|
-
$project: {
|
|
3124
|
+
$project: { [field: string]: any }
|
|
3119
3125
|
}
|
|
3120
3126
|
|
|
3121
3127
|
export interface Redact {
|
package/lib/aggregate.js
CHANGED
|
@@ -892,7 +892,7 @@ Aggregate.prototype.collation = function(collation) {
|
|
|
892
892
|
* const res = await Model.aggregate().facet({
|
|
893
893
|
* books: [{ groupBy: '$author' }],
|
|
894
894
|
* price: [{ $bucketAuto: { groupBy: '$price', buckets: 2 } }]
|
|
895
|
-
*
|
|
895
|
+
* });
|
|
896
896
|
*
|
|
897
897
|
* // Output: { books: [...], price: [{...}, {...}] }
|
|
898
898
|
*
|
package/lib/connection.js
CHANGED
|
@@ -43,10 +43,10 @@ const noPasswordAuthMechanisms = [
|
|
|
43
43
|
* @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
|
|
44
44
|
* @event `connecting`: Emitted when `connection.openUri()` is executed on this connection.
|
|
45
45
|
* @event `connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios.
|
|
46
|
-
* @event `open`: Emitted after we `connected` and `onOpen` is executed on all of this
|
|
46
|
+
* @event `open`: Emitted after we `connected` and `onOpen` is executed on all of this connection's models.
|
|
47
47
|
* @event `disconnecting`: Emitted when `connection.close()` was executed.
|
|
48
48
|
* @event `disconnected`: Emitted after getting disconnected from the db.
|
|
49
|
-
* @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this
|
|
49
|
+
* @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this connection's models.
|
|
50
50
|
* @event `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successful connection.
|
|
51
51
|
* @event `error`: Emitted when an error occurs on this connection.
|
|
52
52
|
* @event `fullsetup`: Emitted after the driver has connected to primary and all secondaries if specified in the connection string.
|
|
@@ -1082,8 +1082,12 @@ Connection.prototype.model = function(name, schema, collection, options) {
|
|
|
1082
1082
|
schema = false;
|
|
1083
1083
|
}
|
|
1084
1084
|
|
|
1085
|
-
if (utils.isObject(schema)
|
|
1086
|
-
|
|
1085
|
+
if (utils.isObject(schema)) {
|
|
1086
|
+
if (!schema.instanceOfSchema) {
|
|
1087
|
+
schema = new Schema(schema);
|
|
1088
|
+
} else if (!(schema instanceof this.base.Schema)) {
|
|
1089
|
+
schema = schema._clone(this.base.Schema);
|
|
1090
|
+
}
|
|
1087
1091
|
}
|
|
1088
1092
|
if (schema && !schema.instanceOfSchema) {
|
|
1089
1093
|
throw new Error('The 2nd parameter to `mongoose.model()` should be a ' +
|
|
@@ -1359,7 +1363,7 @@ Connection.prototype.setClient = function setClient(client) {
|
|
|
1359
1363
|
if (!(client instanceof mongodb.MongoClient)) {
|
|
1360
1364
|
throw new MongooseError('Must call `setClient()` with an instance of MongoClient');
|
|
1361
1365
|
}
|
|
1362
|
-
if (this.
|
|
1366
|
+
if (this.readyState !== STATES.disconnected) {
|
|
1363
1367
|
throw new MongooseError('Cannot call `setClient()` on a connection that is already connected.');
|
|
1364
1368
|
}
|
|
1365
1369
|
if (client.topology == null) {
|
|
@@ -467,7 +467,7 @@ function _nextDoc(ctx, doc, pop, callback) {
|
|
|
467
467
|
});
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
-
|
|
470
|
+
ctx.query._completeOne(doc, null, (err, doc) => {
|
|
471
471
|
if (err != null) {
|
|
472
472
|
return callback(err);
|
|
473
473
|
}
|
|
@@ -496,22 +496,4 @@ function _waitForCursor(ctx, cb) {
|
|
|
496
496
|
});
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
-
/*!
|
|
500
|
-
* Convert a raw doc into a full mongoose doc.
|
|
501
|
-
*/
|
|
502
|
-
|
|
503
|
-
function _create(ctx, doc, populatedIds, cb) {
|
|
504
|
-
const instance = helpers.createModel(ctx.query.model, doc, ctx.query._fields);
|
|
505
|
-
const opts = populatedIds ?
|
|
506
|
-
{ populated: populatedIds } :
|
|
507
|
-
undefined;
|
|
508
|
-
|
|
509
|
-
instance.$init(doc, opts, function(err) {
|
|
510
|
-
if (err) {
|
|
511
|
-
return cb(err);
|
|
512
|
-
}
|
|
513
|
-
cb(null, instance);
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
|
|
517
499
|
module.exports = QueryCursor;
|
package/lib/document.js
CHANGED
|
@@ -91,12 +91,14 @@ function Document(obj, fields, skipId, options) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
this.$__ = new InternalCache;
|
|
94
|
-
this.$__.emitter = new EventEmitter();
|
|
95
94
|
this.$isNew = 'isNew' in options ? options.isNew : true;
|
|
96
95
|
|
|
97
96
|
if ('priorDoc' in options) {
|
|
98
97
|
this.$__.priorDoc = options.priorDoc;
|
|
99
98
|
}
|
|
99
|
+
if (skipId) {
|
|
100
|
+
this.$__.skipId = skipId;
|
|
101
|
+
}
|
|
100
102
|
|
|
101
103
|
if (obj != null && typeof obj !== 'object') {
|
|
102
104
|
throw new ObjectParameterError(obj, 'obj', 'Document');
|
|
@@ -125,14 +127,15 @@ function Document(obj, fields, skipId, options) {
|
|
|
125
127
|
this.$__.activePaths.require(path);
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
this.$__.emitter.setMaxListeners(0);
|
|
129
|
-
|
|
130
130
|
let exclude = null;
|
|
131
131
|
|
|
132
132
|
// determine if this doc is a result of a query with
|
|
133
133
|
// excluded fields
|
|
134
134
|
if (utils.isPOJO(fields)) {
|
|
135
135
|
exclude = isExclusive(fields);
|
|
136
|
+
|
|
137
|
+
this.$__.fields = fields;
|
|
138
|
+
this.$__.exclude = exclude;
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
const hasIncludedChildren = exclude === false && fields ?
|
|
@@ -145,7 +148,7 @@ function Document(obj, fields, skipId, options) {
|
|
|
145
148
|
// By default, defaults get applied **before** setting initial values
|
|
146
149
|
// Re: gh-6155
|
|
147
150
|
if (defaults) {
|
|
148
|
-
$__applyDefaults(this, fields,
|
|
151
|
+
$__applyDefaults(this, fields, exclude, hasIncludedChildren, true, {
|
|
149
152
|
isNew: this.$isNew
|
|
150
153
|
});
|
|
151
154
|
}
|
|
@@ -167,13 +170,11 @@ function Document(obj, fields, skipId, options) {
|
|
|
167
170
|
// see the full doc rather than an empty one, unless they opt out.
|
|
168
171
|
// Re: gh-3781, gh-6155
|
|
169
172
|
if (options.willInit && defaults) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
});
|
|
174
|
-
});
|
|
173
|
+
if (options.skipDefaults) {
|
|
174
|
+
this.$__.skipDefaults = options.skipDefaults;
|
|
175
|
+
}
|
|
175
176
|
} else if (defaults) {
|
|
176
|
-
$__applyDefaults(this, fields,
|
|
177
|
+
$__applyDefaults(this, fields, exclude, hasIncludedChildren, false, options.skipDefaults, {
|
|
177
178
|
isNew: this.$isNew
|
|
178
179
|
});
|
|
179
180
|
}
|
|
@@ -222,6 +223,15 @@ utils.each(
|
|
|
222
223
|
'removeAllListeners', 'addListener'],
|
|
223
224
|
function(emitterFn) {
|
|
224
225
|
Document.prototype[emitterFn] = function() {
|
|
226
|
+
// Delay creating emitter until necessary because emitters take up a lot of memory,
|
|
227
|
+
// especially for subdocuments.
|
|
228
|
+
if (!this.$__.emitter) {
|
|
229
|
+
if (emitterFn === 'emit') {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
this.$__.emitter = new EventEmitter();
|
|
233
|
+
this.$__.emitter.setMaxListeners(0);
|
|
234
|
+
}
|
|
225
235
|
return this.$__.emitter[emitterFn].apply(this.$__.emitter, arguments);
|
|
226
236
|
};
|
|
227
237
|
Document.prototype[`$${emitterFn}`] = Document.prototype[emitterFn];
|
|
@@ -416,12 +426,18 @@ function $__hasIncludedChildren(fields) {
|
|
|
416
426
|
const keys = Object.keys(fields);
|
|
417
427
|
|
|
418
428
|
for (const key of keys) {
|
|
429
|
+
if (key.indexOf('.') === -1) {
|
|
430
|
+
hasIncludedChildren[key] = 1;
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
419
433
|
const parts = key.split('.');
|
|
420
|
-
|
|
434
|
+
let c = parts[0];
|
|
421
435
|
|
|
422
|
-
for (
|
|
423
|
-
c
|
|
424
|
-
|
|
436
|
+
for (let i = 0; i < parts.length; ++i) {
|
|
437
|
+
hasIncludedChildren[c] = 1;
|
|
438
|
+
if (i + 1 < parts.length) {
|
|
439
|
+
c = c + '.' + parts[i + 1];
|
|
440
|
+
}
|
|
425
441
|
}
|
|
426
442
|
}
|
|
427
443
|
|
|
@@ -432,7 +448,7 @@ function $__hasIncludedChildren(fields) {
|
|
|
432
448
|
* ignore
|
|
433
449
|
*/
|
|
434
450
|
|
|
435
|
-
function $__applyDefaults(doc, fields,
|
|
451
|
+
function $__applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSetters, pathsToSkip) {
|
|
436
452
|
const paths = Object.keys(doc.$__schema.paths);
|
|
437
453
|
const plen = paths.length;
|
|
438
454
|
|
|
@@ -441,7 +457,7 @@ function $__applyDefaults(doc, fields, skipId, exclude, hasIncludedChildren, isB
|
|
|
441
457
|
let curPath = '';
|
|
442
458
|
const p = paths[i];
|
|
443
459
|
|
|
444
|
-
if (p === '_id' && skipId) {
|
|
460
|
+
if (p === '_id' && doc.$__.skipId) {
|
|
445
461
|
continue;
|
|
446
462
|
}
|
|
447
463
|
|
|
@@ -720,13 +736,8 @@ Document.prototype.$init = function() {
|
|
|
720
736
|
return this.constructor.prototype.init.apply(this, arguments);
|
|
721
737
|
};
|
|
722
738
|
|
|
723
|
-
/*!
|
|
724
|
-
* ignore
|
|
725
|
-
*/
|
|
726
|
-
|
|
727
739
|
Document.prototype.$__init = function(doc, opts) {
|
|
728
740
|
this.$isNew = false;
|
|
729
|
-
this.$init = true;
|
|
730
741
|
opts = opts || {};
|
|
731
742
|
|
|
732
743
|
// handle docs with populated paths
|
|
@@ -761,6 +772,12 @@ Document.prototype.$__init = function(doc, opts) {
|
|
|
761
772
|
this.constructor.emit('init', this);
|
|
762
773
|
|
|
763
774
|
this.$__._id = this._id;
|
|
775
|
+
|
|
776
|
+
const hasIncludedChildren = this.$__.exclude === false && this.$__.fields ?
|
|
777
|
+
$__hasIncludedChildren(this.$__.fields) :
|
|
778
|
+
{};
|
|
779
|
+
$__applyDefaults(this, this.$__.fields, this.$__.exclude, hasIncludedChildren, false, this.$__.skipDefaults);
|
|
780
|
+
|
|
764
781
|
return this;
|
|
765
782
|
};
|
|
766
783
|
|
|
@@ -820,8 +837,7 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
820
837
|
if (obj[i] === null) {
|
|
821
838
|
doc[i] = schema._castNullish(null);
|
|
822
839
|
} else if (obj[i] !== undefined) {
|
|
823
|
-
const
|
|
824
|
-
const wasPopulated = intCache.wasPopulated || null;
|
|
840
|
+
const wasPopulated = obj[i].$__ == null ? null : obj[i].$__.wasPopulated;
|
|
825
841
|
|
|
826
842
|
if (schema && !wasPopulated) {
|
|
827
843
|
try {
|
|
@@ -988,10 +1004,13 @@ Document.prototype.$session = function $session(session) {
|
|
|
988
1004
|
'called `endSession()` on the session you are passing to `$session()`.');
|
|
989
1005
|
}
|
|
990
1006
|
|
|
991
|
-
this.$__.session
|
|
1007
|
+
if (session == null && this.$__.session == null) {
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
992
1010
|
|
|
1011
|
+
this.$__.session = session;
|
|
993
1012
|
|
|
994
|
-
if (!this.$
|
|
1013
|
+
if (!this.$isSubdocument) {
|
|
995
1014
|
const subdocs = this.$getAllSubdocs();
|
|
996
1015
|
for (const child of subdocs) {
|
|
997
1016
|
child.$session(session);
|
|
@@ -1143,13 +1162,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1143
1162
|
}
|
|
1144
1163
|
|
|
1145
1164
|
if (pathtype === 'real' || pathtype === 'virtual') {
|
|
1146
|
-
|
|
1147
|
-
let p = path[key];
|
|
1148
|
-
if (this.$__schema.paths[pathName] &&
|
|
1149
|
-
this.$__schema.paths[pathName].$isSingleNested &&
|
|
1150
|
-
path[key] instanceof Document) {
|
|
1151
|
-
p = p.toObject({ virtuals: false, transform: false });
|
|
1152
|
-
}
|
|
1165
|
+
const p = path[key];
|
|
1153
1166
|
this.$set(prefix + key, p, constructing, options);
|
|
1154
1167
|
} else if (pathtype === 'nested' && path[key] instanceof Document) {
|
|
1155
1168
|
this.$set(prefix + key,
|
|
@@ -1410,7 +1423,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1410
1423
|
didPopulate = true;
|
|
1411
1424
|
}
|
|
1412
1425
|
|
|
1413
|
-
if (this.$__schema.singleNestedPaths[path] == null) {
|
|
1426
|
+
if (this.$__schema.singleNestedPaths[path] == null && (!refMatches || !schema.$isSingleNested || !val.$__)) {
|
|
1414
1427
|
// If this path is underneath a single nested schema, we'll call the setter
|
|
1415
1428
|
// later in `$__set()` because we don't take `_doc` when we iterate through
|
|
1416
1429
|
// a single nested doc. That's to make sure we get the correct context.
|
|
@@ -1468,9 +1481,9 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1468
1481
|
}
|
|
1469
1482
|
|
|
1470
1483
|
if (shouldSet) {
|
|
1471
|
-
const doc = this.$
|
|
1484
|
+
const doc = this.$isSubdocument ? this.ownerDocument() : this;
|
|
1472
1485
|
const savedState = doc.$__.savedState;
|
|
1473
|
-
const savedStatePath = this.$
|
|
1486
|
+
const savedStatePath = this.$isSubdocument ? this.$__.fullPath + '.' + path : path;
|
|
1474
1487
|
if (savedState != null) {
|
|
1475
1488
|
const firstDot = savedStatePath.indexOf('.');
|
|
1476
1489
|
const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot);
|
|
@@ -1844,7 +1857,7 @@ Document.prototype.$__path = function(path) {
|
|
|
1844
1857
|
|
|
1845
1858
|
Document.prototype.markModified = function(path, scope) {
|
|
1846
1859
|
this.$__.activePaths.modify(path);
|
|
1847
|
-
if (scope != null && !this.$
|
|
1860
|
+
if (scope != null && !this.$isSubdocument) {
|
|
1848
1861
|
this.$__.pathsToScopes = this.$__pathsToScopes || {};
|
|
1849
1862
|
this.$__.pathsToScopes[path] = scope;
|
|
1850
1863
|
}
|
|
@@ -2061,11 +2074,15 @@ Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
|
|
|
2061
2074
|
|
|
2062
2075
|
Document.prototype.isModified = function(paths, modifiedPaths) {
|
|
2063
2076
|
if (paths) {
|
|
2077
|
+
const directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
|
|
2078
|
+
if (directModifiedPaths.length === 0) {
|
|
2079
|
+
return false;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2064
2082
|
if (!Array.isArray(paths)) {
|
|
2065
|
-
paths = paths.split(' ');
|
|
2083
|
+
paths = paths.indexOf(' ') === -1 ? [paths] : paths.split(' ');
|
|
2066
2084
|
}
|
|
2067
2085
|
const modified = modifiedPaths || this[documentModifiedPaths]();
|
|
2068
|
-
const directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
|
|
2069
2086
|
const isModifiedChild = paths.some(function(path) {
|
|
2070
2087
|
return !!~modified.indexOf(path);
|
|
2071
2088
|
});
|
|
@@ -2222,7 +2239,9 @@ Document.prototype.isSelected = function isSelected(path) {
|
|
|
2222
2239
|
if (this.$__.selected == null) {
|
|
2223
2240
|
return true;
|
|
2224
2241
|
}
|
|
2225
|
-
|
|
2242
|
+
if (!path) {
|
|
2243
|
+
return false;
|
|
2244
|
+
}
|
|
2226
2245
|
if (path === '_id') {
|
|
2227
2246
|
return this.$__.selected._id !== 0;
|
|
2228
2247
|
}
|
|
@@ -2372,7 +2391,7 @@ Document.prototype.validate = function(pathsToValidate, options, callback) {
|
|
|
2372
2391
|
let parallelValidate;
|
|
2373
2392
|
this.$op = 'validate';
|
|
2374
2393
|
|
|
2375
|
-
if (this.$
|
|
2394
|
+
if (this.$isSubdocument != null) {
|
|
2376
2395
|
// Skip parallel validate check for subdocuments
|
|
2377
2396
|
} else if (this.$__.validating) {
|
|
2378
2397
|
parallelValidate = new ParallelValidateError(this, {
|
|
@@ -3119,7 +3138,7 @@ Document.prototype.$__reset = function reset() {
|
|
|
3119
3138
|
doc.$__reset();
|
|
3120
3139
|
if (doc.$parent() === _this) {
|
|
3121
3140
|
_this.$__.activePaths.init(doc.$basePath);
|
|
3122
|
-
} else if (doc.$parent() != null && doc.$parent().$
|
|
3141
|
+
} else if (doc.$parent() != null && doc.$parent().$isSubdocument) {
|
|
3123
3142
|
// If map path underneath subdocument, may end up with a case where
|
|
3124
3143
|
// map path is modified but parent still needs to be reset. See gh-10295
|
|
3125
3144
|
doc.$parent().$__reset();
|
|
@@ -3971,7 +3990,7 @@ Document.prototype.ownerDocument = function() {
|
|
|
3971
3990
|
*/
|
|
3972
3991
|
|
|
3973
3992
|
Document.prototype.parent = function() {
|
|
3974
|
-
if (this.$
|
|
3993
|
+
if (this.$isSubdocument || this.$__.wasPopulated) {
|
|
3975
3994
|
return this.$__.parent;
|
|
3976
3995
|
}
|
|
3977
3996
|
return this;
|
package/lib/helpers/common.js
CHANGED
|
@@ -19,7 +19,7 @@ exports.modifiedPaths = modifiedPaths;
|
|
|
19
19
|
function flatten(update, path, options, schema) {
|
|
20
20
|
let keys;
|
|
21
21
|
if (update && isMongooseObject(update) && !Buffer.isBuffer(update)) {
|
|
22
|
-
keys = Object.keys(update.toObject({ transform: false, virtuals: false }));
|
|
22
|
+
keys = Object.keys(update.toObject({ transform: false, virtuals: false }) || {});
|
|
23
23
|
} else {
|
|
24
24
|
keys = Object.keys(update || {});
|
|
25
25
|
}
|
|
@@ -22,6 +22,12 @@ module.exports = function cleanModifiedSubpaths(doc, path, options) {
|
|
|
22
22
|
if (modifiedPath.startsWith(path + '.')) {
|
|
23
23
|
delete doc.$__.activePaths.states.modify[modifiedPath];
|
|
24
24
|
++deleted;
|
|
25
|
+
|
|
26
|
+
if (doc.$isSubdocument) {
|
|
27
|
+
const owner = doc.ownerDocument();
|
|
28
|
+
const fullPath = doc.$__fullPath(modifiedPath);
|
|
29
|
+
delete owner.$__.activePaths.states.modify[fullPath];
|
|
30
|
+
}
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
33
|
return deleted;
|