@nullix/zod-mongoose-studio 1.0.13 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{Db4IAypj.js → 0J_bLG6U.js} +1 -1
- package/.output/public/_nuxt/{Y39o1QEi.js → 5KLjKHc1.js} +1 -1
- package/.output/public/_nuxt/{B4zoPYF-.js → B2UrsJHg.js} +1 -1
- package/.output/public/_nuxt/{BSqjh6Vk.js → BC5hGokz.js} +1 -1
- package/.output/public/_nuxt/{BS4yU4O0.js → BJwN20Xm.js} +1 -1
- package/.output/public/_nuxt/{D8_n84hl.js → BMgDPqps.js} +1 -1
- package/.output/public/_nuxt/{CqNsQbt9.js → B_sGF2qN.js} +1 -1
- package/.output/public/_nuxt/{NAqlztEN.js → BeaJ7I-K.js} +10 -10
- package/.output/public/_nuxt/{WZ0WK9cR.js → BkE1sm_1.js} +1 -1
- package/.output/public/_nuxt/{kBtP64Rx.js → CADbZwE5.js} +1 -1
- package/.output/public/_nuxt/{B8qGaxNm.js → CB0WRoVi.js} +1 -1
- package/.output/public/_nuxt/{BV6uALfO.js → CCh0PVV0.js} +1 -1
- package/.output/public/_nuxt/{CP9Z7-_9.js → Cr0GW7rA.js} +1 -1
- package/.output/public/_nuxt/{DeCqoVOS.js → DJe7Wxdv.js} +1 -1
- package/.output/public/_nuxt/{dBZQW7JD.js → DRBrUaE5.js} +1 -1
- package/.output/public/_nuxt/{Db19R32y.js → DV2n9B6m.js} +1 -1
- package/.output/public/_nuxt/{CvnpbYw0.js → DVD-jGiv.js} +1 -1
- package/.output/public/_nuxt/{BWajNATZ.js → Dk9qGA5X.js} +3 -3
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/dc761332-547d-4953-b51d-b2d453009b48.json +1 -0
- package/.output/public/_nuxt/error-404.64pZEiDn.css +1 -0
- package/.output/public/_nuxt/error-500.DHOpI0Ir.css +1 -0
- package/.output/public/_nuxt/{BoHhCIKW.js → koEZfutw.js} +3 -3
- package/.output/public/_nuxt/{B_782F4p.js → r6LdR7DN.js} +1 -1
- package/.output/public/_nuxt/{BEI71c6K.js → rEfOp38p.js} +1 -1
- package/.output/server/chunks/_/error-500.mjs.map +1 -1
- package/.output/server/chunks/build/client.precomputed.mjs +1 -1
- package/.output/server/chunks/build/{error-404-8tbBXju4.mjs → error-404-BN-7rNE4.mjs} +4 -4
- package/.output/server/chunks/build/error-404-BN-7rNE4.mjs.map +1 -0
- package/.output/server/chunks/build/error-404-styles.Byx46oLR.mjs +8 -0
- package/.output/server/chunks/build/error-404-styles.Byx46oLR.mjs.map +1 -0
- package/.output/server/chunks/build/{error-500-DxFsom1i.mjs → error-500-DhIQ-2yt.mjs} +4 -4
- package/.output/server/chunks/build/error-500-DhIQ-2yt.mjs.map +1 -0
- package/.output/server/chunks/build/error-500-styles.BL3UT0Wa.mjs +8 -0
- package/.output/server/chunks/build/error-500-styles.BL3UT0Wa.mjs.map +1 -0
- package/.output/server/chunks/build/{index-BB-Clavm.mjs → index-Dnrh1ePF.mjs} +1 -1
- package/.output/server/chunks/build/index-Dnrh1ePF.mjs.map +1 -0
- package/.output/server/chunks/build/server.mjs +9 -9
- package/.output/server/chunks/build/styles.mjs +4 -4
- package/.output/server/chunks/nitro/nitro.mjs +333 -333
- package/.output/server/chunks/nitro/nitro.mjs.map +1 -1
- package/.output/server/chunks/routes/renderer.mjs.map +1 -1
- package/.output/server/node_modules/bson/lib/bson.cjs +157 -48
- package/.output/server/node_modules/bson/package.json +9 -11
- package/.output/server/node_modules/kareem/index.js +228 -343
- package/.output/server/node_modules/kareem/package.json +3 -3
- package/.output/server/node_modules/mongodb/lib/bson.js +27 -5
- package/.output/server/node_modules/mongodb/lib/bulk/common.js +7 -9
- package/.output/server/node_modules/mongodb/lib/change_stream.js +91 -39
- package/.output/server/node_modules/mongodb/lib/client-side-encryption/auto_encrypter.js +21 -14
- package/.output/server/node_modules/mongodb/lib/client-side-encryption/client_encryption.js +2 -5
- package/.output/server/node_modules/mongodb/lib/client-side-encryption/errors.js +3 -1
- package/.output/server/node_modules/mongodb/lib/client-side-encryption/mongocryptd_manager.js +1 -1
- package/.output/server/node_modules/mongodb/lib/client-side-encryption/state_machine.js +1 -0
- package/.output/server/node_modules/mongodb/lib/cmap/auth/aws4.js +161 -0
- package/.output/server/node_modules/mongodb/lib/cmap/auth/aws_temporary_credentials.js +11 -58
- package/.output/server/node_modules/mongodb/lib/cmap/auth/gssapi.js +4 -6
- package/.output/server/node_modules/mongodb/lib/cmap/auth/mongo_credentials.js +2 -16
- package/.output/server/node_modules/mongodb/lib/cmap/auth/mongodb_aws.js +14 -23
- package/.output/server/node_modules/mongodb/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +3 -3
- package/.output/server/node_modules/mongodb/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +3 -3
- package/.output/server/node_modules/mongodb/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +4 -3
- package/.output/server/node_modules/mongodb/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +4 -3
- package/.output/server/node_modules/mongodb/lib/cmap/auth/mongodb_oidc.js +4 -4
- package/.output/server/node_modules/mongodb/lib/cmap/auth/plain.js +1 -1
- package/.output/server/node_modules/mongodb/lib/cmap/auth/providers.js +0 -1
- package/.output/server/node_modules/mongodb/lib/cmap/auth/scram.js +53 -40
- package/.output/server/node_modules/mongodb/lib/cmap/commands.js +46 -39
- package/.output/server/node_modules/mongodb/lib/cmap/connect.js +35 -3
- package/.output/server/node_modules/mongodb/lib/cmap/connection.js +36 -32
- package/.output/server/node_modules/mongodb/lib/cmap/connection_pool.js +67 -67
- package/.output/server/node_modules/mongodb/lib/cmap/connection_pool_events.js +3 -3
- package/.output/server/node_modules/mongodb/lib/cmap/errors.js +1 -1
- package/.output/server/node_modules/mongodb/lib/cmap/handshake/client_metadata.js +15 -13
- package/.output/server/node_modules/mongodb/lib/cmap/metrics.js +3 -3
- package/.output/server/node_modules/mongodb/lib/cmap/wire_protocol/compression.js +26 -10
- package/.output/server/node_modules/mongodb/lib/cmap/wire_protocol/constants.js +3 -1
- package/.output/server/node_modules/mongodb/lib/cmap/wire_protocol/on_data.js +0 -1
- package/.output/server/node_modules/mongodb/lib/cmap/wire_protocol/on_demand/document.js +9 -9
- package/.output/server/node_modules/mongodb/lib/cmap/wire_protocol/responses.js +2 -2
- package/.output/server/node_modules/mongodb/lib/collection.js +1 -1
- package/.output/server/node_modules/mongodb/lib/connection_string.js +30 -15
- package/.output/server/node_modules/mongodb/lib/cursor/abstract_cursor.js +17 -34
- package/.output/server/node_modules/mongodb/lib/cursor/change_stream_cursor.js +2 -2
- package/.output/server/node_modules/mongodb/lib/cursor/find_cursor.js +37 -26
- package/.output/server/node_modules/mongodb/lib/cursor/run_command_cursor.js +1 -1
- package/.output/server/node_modules/mongodb/lib/db.js +6 -7
- package/.output/server/node_modules/mongodb/lib/deps.js +0 -13
- package/.output/server/node_modules/mongodb/lib/error.js +7 -10
- package/.output/server/node_modules/mongodb/lib/gridfs/download.js +7 -6
- package/.output/server/node_modules/mongodb/lib/gridfs/index.js +9 -9
- package/.output/server/node_modules/mongodb/lib/gridfs/upload.js +17 -23
- package/.output/server/node_modules/mongodb/lib/index.js +2 -4
- package/.output/server/node_modules/mongodb/lib/mongo_client.js +58 -67
- package/.output/server/node_modules/mongodb/lib/mongo_client_auth_providers.js +0 -6
- package/.output/server/node_modules/mongodb/lib/mongo_logger.js +11 -5
- package/.output/server/node_modules/mongodb/lib/mongo_types.js +1 -2
- package/.output/server/node_modules/mongodb/lib/operations/aggregate.js +0 -3
- package/.output/server/node_modules/mongodb/lib/operations/create_collection.js +0 -1
- package/.output/server/node_modules/mongodb/lib/operations/drop.js +8 -9
- package/.output/server/node_modules/mongodb/lib/operations/end_sessions.js +34 -0
- package/.output/server/node_modules/mongodb/lib/operations/execute_operation.js +121 -45
- package/.output/server/node_modules/mongodb/lib/operations/operation.js +1 -0
- package/.output/server/node_modules/mongodb/lib/read_preference.js +10 -14
- package/.output/server/node_modules/mongodb/lib/runtime_adapters.js +32 -0
- package/.output/server/node_modules/mongodb/lib/sdam/monitor.js +8 -8
- package/.output/server/node_modules/mongodb/lib/sdam/server.js +55 -43
- package/.output/server/node_modules/mongodb/lib/sdam/server_description.js +1 -1
- package/.output/server/node_modules/mongodb/lib/sdam/server_selection.js +135 -72
- package/.output/server/node_modules/mongodb/lib/sdam/srv_polling.js +3 -3
- package/.output/server/node_modules/mongodb/lib/sdam/topology.js +37 -77
- package/.output/server/node_modules/mongodb/lib/sdam/topology_description.js +1 -1
- package/.output/server/node_modules/mongodb/lib/sessions.js +150 -40
- package/.output/server/node_modules/mongodb/lib/transactions.js +2 -13
- package/.output/server/node_modules/mongodb/lib/utils.js +42 -90
- package/.output/server/node_modules/mongodb/package.json +49 -45
- package/.output/server/node_modules/mongodb-connection-string-url/lib/index.js +45 -19
- package/.output/server/node_modules/mongodb-connection-string-url/lib/redact.js +30 -19
- package/.output/server/node_modules/mongodb-connection-string-url/package.json +25 -16
- package/.output/server/node_modules/mongoose/lib/aggregate.js +108 -127
- package/.output/server/node_modules/mongoose/lib/cast/bigint.js +3 -3
- package/.output/server/node_modules/mongoose/lib/cast/boolean.js +3 -3
- package/.output/server/node_modules/mongoose/lib/cast/double.js +4 -4
- package/.output/server/node_modules/mongoose/lib/cast/int32.js +2 -2
- package/.output/server/node_modules/mongoose/lib/cast/number.js +6 -6
- package/.output/server/node_modules/mongoose/lib/cast/string.js +3 -3
- package/.output/server/node_modules/mongoose/lib/cast/uuid.js +5 -48
- package/.output/server/node_modules/mongoose/lib/cast.js +16 -24
- package/.output/server/node_modules/mongoose/lib/collection.js +6 -6
- package/.output/server/node_modules/mongoose/lib/connection.js +108 -105
- package/.output/server/node_modules/mongoose/lib/cursor/aggregationCursor.js +23 -33
- package/.output/server/node_modules/mongoose/lib/cursor/changeStream.js +60 -40
- package/.output/server/node_modules/mongoose/lib/cursor/queryCursor.js +21 -25
- package/.output/server/node_modules/mongoose/lib/document.js +712 -531
- package/.output/server/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js +85 -130
- package/.output/server/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js +32 -41
- package/.output/server/node_modules/mongoose/lib/error/cast.js +21 -12
- package/.output/server/node_modules/mongoose/lib/error/createCollectionsError.js +2 -2
- package/.output/server/node_modules/mongoose/lib/error/divergentArray.js +1 -1
- package/.output/server/node_modules/mongoose/lib/error/eachAsyncMultiError.js +1 -1
- package/.output/server/node_modules/mongoose/lib/error/index.js +3 -3
- package/.output/server/node_modules/mongoose/lib/error/invalidSchemaOption.js +1 -1
- package/.output/server/node_modules/mongoose/lib/error/messages.js +1 -0
- package/.output/server/node_modules/mongoose/lib/error/missingSchema.js +1 -1
- package/.output/server/node_modules/mongoose/lib/error/objectParameter.js +4 -5
- package/.output/server/node_modules/mongoose/lib/error/overwriteModel.js +1 -1
- package/.output/server/node_modules/mongoose/lib/error/setOptionError.js +3 -3
- package/.output/server/node_modules/mongoose/lib/error/strict.js +3 -3
- package/.output/server/node_modules/mongoose/lib/error/strictPopulate.js +2 -2
- package/.output/server/node_modules/mongoose/lib/error/syncIndexes.js +2 -2
- package/.output/server/node_modules/mongoose/lib/error/validation.js +2 -10
- package/.output/server/node_modules/mongoose/lib/error/validator.js +1 -1
- package/.output/server/node_modules/mongoose/lib/error/version.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/aggregate/prepareDiscriminatorPipeline.js +4 -4
- package/.output/server/node_modules/mongoose/lib/helpers/buildMiddlewareFilter.js +24 -0
- package/.output/server/node_modules/mongoose/lib/helpers/clone.js +35 -18
- package/.output/server/node_modules/mongoose/lib/helpers/common.js +5 -5
- package/.output/server/node_modules/mongoose/lib/helpers/cursor/eachAsync.js +4 -4
- package/.output/server/node_modules/mongoose/lib/helpers/discriminator/getConstructor.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/discriminator/getDiscriminatorByValue.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/discriminator/mergeDiscriminatorSchema.js +10 -5
- package/.output/server/node_modules/mongoose/lib/helpers/document/applyDefaults.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/document/applyTimestamps.js +11 -10
- package/.output/server/node_modules/mongoose/lib/helpers/document/applyVirtuals.js +10 -9
- package/.output/server/node_modules/mongoose/lib/helpers/document/cleanModifiedSubpaths.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/document/compile.js +17 -14
- package/.output/server/node_modules/mongoose/lib/helpers/document/getDeepestSubdocumentForPath.js +3 -3
- package/.output/server/node_modules/mongoose/lib/helpers/document/getEmbeddedDiscriminatorPath.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/document/isInPathsToSave.js +24 -0
- package/.output/server/node_modules/mongoose/lib/helpers/get.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/indexes/decorateDiscriminatorIndexOptions.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/indexes/getRelatedIndexes.js +3 -3
- package/.output/server/node_modules/mongoose/lib/helpers/indexes/isIndexEqual.js +3 -4
- package/.output/server/node_modules/mongoose/lib/helpers/indexes/isIndexSpecEqual.js +3 -3
- package/.output/server/node_modules/mongoose/lib/helpers/isBsonType.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/isMongooseObject.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/isObject.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/isSimpleValidator.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/minimize.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/model/applyDefaultsToPOJO.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/model/applyHooks.js +55 -54
- package/.output/server/node_modules/mongoose/lib/helpers/model/applyMethods.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/model/applyStaticHooks.js +1 -48
- package/.output/server/node_modules/mongoose/lib/helpers/model/castBulkWrite.js +8 -12
- package/.output/server/node_modules/mongoose/lib/helpers/model/discriminator.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/parallelLimit.js +18 -36
- package/.output/server/node_modules/mongoose/lib/helpers/pluralize.js +4 -4
- package/.output/server/node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js +4 -11
- package/.output/server/node_modules/mongoose/lib/helpers/populate/assignVals.js +10 -10
- package/.output/server/node_modules/mongoose/lib/helpers/populate/createPopulateQueryFilter.js +3 -3
- package/.output/server/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js +197 -69
- package/.output/server/node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js +15 -15
- package/.output/server/node_modules/mongoose/lib/helpers/populate/markArraySubdocsPopulated.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/populate/modelNamesFromRefPath.js +10 -2
- package/.output/server/node_modules/mongoose/lib/helpers/populate/setPopulatedVirtualValue.js +5 -5
- package/.output/server/node_modules/mongoose/lib/helpers/printJestWarning.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/processConnectionOptions.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/projection/hasIncludedChildren.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/projection/isPathExcluded.js +3 -3
- package/.output/server/node_modules/mongoose/lib/helpers/projection/isSubpath.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/projection/parseProjection.js +9 -4
- package/.output/server/node_modules/mongoose/lib/helpers/query/cast$expr.js +8 -10
- package/.output/server/node_modules/mongoose/lib/helpers/query/castFilterPath.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/query/castUpdate.js +44 -38
- package/.output/server/node_modules/mongoose/lib/helpers/query/getEmbeddedDiscriminatorPath.js +8 -8
- package/.output/server/node_modules/mongoose/lib/helpers/query/handleImmutable.js +8 -8
- package/.output/server/node_modules/mongoose/lib/helpers/schema/applyPlugins.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/schema/applyReadConcern.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/schema/applyWriteConcern.js +4 -2
- package/.output/server/node_modules/mongoose/lib/helpers/schema/getIndexes.js +5 -11
- package/.output/server/node_modules/mongoose/lib/helpers/schema/getSubdocumentStrictValue.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/schema/handleIdOption.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/schema/idGetter.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/schematype/handleImmutable.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/setDefaultsOnInsert.js +26 -13
- package/.output/server/node_modules/mongoose/lib/helpers/timestamps/setDocumentTimestamps.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/timestamps/setupTimestamps.js +60 -38
- package/.output/server/node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js +13 -10
- package/.output/server/node_modules/mongoose/lib/helpers/update/castArrayFilters.js +4 -4
- package/.output/server/node_modules/mongoose/lib/helpers/update/decorateUpdateWithVersionKey.js +1 -1
- package/.output/server/node_modules/mongoose/lib/helpers/update/modifiedPaths.js +2 -2
- package/.output/server/node_modules/mongoose/lib/helpers/update/removeUnusedArrayFilters.js +7 -2
- package/.output/server/node_modules/mongoose/lib/helpers/updateValidators.js +58 -119
- package/.output/server/node_modules/mongoose/lib/model.js +940 -946
- package/.output/server/node_modules/mongoose/lib/mongoose.js +131 -79
- package/.output/server/node_modules/mongoose/lib/options/schemaArrayOptions.js +2 -2
- package/.output/server/node_modules/mongoose/lib/options/schemaBufferOptions.js +1 -1
- package/.output/server/node_modules/mongoose/lib/options/schemaDocumentArrayOptions.js +23 -0
- package/.output/server/node_modules/mongoose/lib/options/schemaNumberOptions.js +3 -3
- package/.output/server/node_modules/mongoose/lib/options/schemaObjectIdOptions.js +2 -2
- package/.output/server/node_modules/mongoose/lib/options/schemaStringOptions.js +6 -6
- package/.output/server/node_modules/mongoose/lib/options/schemaSubdocumentOptions.js +23 -0
- package/.output/server/node_modules/mongoose/lib/options/schemaTypeOptions.js +27 -13
- package/.output/server/node_modules/mongoose/lib/options/virtualOptions.js +12 -12
- package/.output/server/node_modules/mongoose/lib/plugins/index.js +0 -1
- package/.output/server/node_modules/mongoose/lib/plugins/saveSubdocs.js +84 -92
- package/.output/server/node_modules/mongoose/lib/plugins/sharding.js +33 -15
- package/.output/server/node_modules/mongoose/lib/plugins/trackTransaction.js +29 -25
- package/.output/server/node_modules/mongoose/lib/query.js +700 -548
- package/.output/server/node_modules/mongoose/lib/queryHelpers.js +34 -32
- package/.output/server/node_modules/mongoose/lib/schema/array.js +69 -113
- package/.output/server/node_modules/mongoose/lib/schema/bigint.js +18 -20
- package/.output/server/node_modules/mongoose/lib/schema/boolean.js +20 -22
- package/.output/server/node_modules/mongoose/lib/schema/buffer.js +23 -25
- package/.output/server/node_modules/mongoose/lib/schema/date.js +19 -21
- package/.output/server/node_modules/mongoose/lib/schema/decimal128.js +16 -18
- package/.output/server/node_modules/mongoose/lib/schema/documentArray.js +94 -131
- package/.output/server/node_modules/mongoose/lib/schema/documentArrayElement.js +50 -16
- package/.output/server/node_modules/mongoose/lib/schema/double.js +16 -18
- package/.output/server/node_modules/mongoose/lib/schema/index.js +1 -0
- package/.output/server/node_modules/mongoose/lib/schema/int32.js +17 -19
- package/.output/server/node_modules/mongoose/lib/schema/map.js +17 -24
- package/.output/server/node_modules/mongoose/lib/schema/mixed.js +14 -14
- package/.output/server/node_modules/mongoose/lib/schema/number.js +38 -28
- package/.output/server/node_modules/mongoose/lib/schema/objectId.js +18 -20
- package/.output/server/node_modules/mongoose/lib/schema/operators/exists.js +1 -1
- package/.output/server/node_modules/mongoose/lib/schema/operators/geospatial.js +1 -1
- package/.output/server/node_modules/mongoose/lib/schema/operators/text.js +4 -4
- package/.output/server/node_modules/mongoose/lib/schema/string.js +42 -27
- package/.output/server/node_modules/mongoose/lib/schema/subdocument.js +47 -58
- package/.output/server/node_modules/mongoose/lib/schema/union.js +54 -4
- package/.output/server/node_modules/mongoose/lib/schema/uuid.js +17 -40
- package/.output/server/node_modules/mongoose/lib/schema.js +235 -176
- package/.output/server/node_modules/mongoose/lib/schemaType.js +227 -158
- package/.output/server/node_modules/mongoose/lib/stateMachine.js +5 -8
- package/.output/server/node_modules/mongoose/lib/types/array/index.js +5 -5
- package/.output/server/node_modules/mongoose/lib/types/array/methods/index.js +27 -28
- package/.output/server/node_modules/mongoose/lib/types/arraySubdocument.js +11 -11
- package/.output/server/node_modules/mongoose/lib/types/buffer.js +15 -15
- package/.output/server/node_modules/mongoose/lib/types/decimal128.js +1 -1
- package/.output/server/node_modules/mongoose/lib/types/documentArray/index.js +4 -4
- package/.output/server/node_modules/mongoose/lib/types/documentArray/methods/index.js +15 -13
- package/.output/server/node_modules/mongoose/lib/types/double.js +1 -1
- package/.output/server/node_modules/mongoose/lib/types/map.js +20 -71
- package/.output/server/node_modules/mongoose/lib/types/objectid.js +1 -1
- package/.output/server/node_modules/mongoose/lib/types/subdocument.js +32 -81
- package/.output/server/node_modules/mongoose/lib/types/uuid.js +1 -1
- package/.output/server/node_modules/mongoose/lib/utils.js +91 -70
- package/.output/server/node_modules/mongoose/lib/validOptions.js +4 -3
- package/.output/server/node_modules/mongoose/lib/virtualType.js +18 -18
- package/.output/server/node_modules/mongoose/package.json +46 -63
- package/.output/server/node_modules/mquery/lib/collection/collection.js +3 -1
- package/.output/server/node_modules/mquery/lib/collection/node.js +17 -3
- package/.output/server/node_modules/mquery/lib/mquery.js +136 -93
- package/.output/server/node_modules/mquery/lib/permissions.js +21 -6
- package/.output/server/node_modules/mquery/package.json +4 -7
- package/.output/server/package.json +7 -9
- package/package.json +3 -3
- package/.output/public/_nuxt/builds/meta/0d6006db-fbb0-4297-85cf-bf92ceafcb79.json +0 -1
- package/.output/public/_nuxt/error-404.CTWLHxjC.css +0 -1
- package/.output/public/_nuxt/error-500.UBfk8-QP.css +0 -1
- package/.output/server/chunks/build/error-404-8tbBXju4.mjs.map +0 -1
- package/.output/server/chunks/build/error-404-styles.BeWfK6Py.mjs +0 -8
- package/.output/server/chunks/build/error-404-styles.BeWfK6Py.mjs.map +0 -1
- package/.output/server/chunks/build/error-500-DxFsom1i.mjs.map +0 -1
- package/.output/server/chunks/build/error-500-styles.CPUUvoY-.mjs +0 -8
- package/.output/server/chunks/build/error-500-styles.CPUUvoY-.mjs.map +0 -1
- package/.output/server/chunks/build/index-BB-Clavm.mjs.map +0 -1
- package/.output/server/node_modules/debug/package.json +0 -64
- package/.output/server/node_modules/debug/src/browser.js +0 -272
- package/.output/server/node_modules/debug/src/common.js +0 -292
- package/.output/server/node_modules/debug/src/index.js +0 -10
- package/.output/server/node_modules/debug/src/node.js +0 -263
- package/.output/server/node_modules/mongodb/lib/client-side-encryption/crypto_callbacks.js +0 -81
- package/.output/server/node_modules/mongodb/lib/resource_management.js +0 -58
- package/.output/server/node_modules/mongoose/lib/browserDocument.js +0 -101
- package/.output/server/node_modules/mongoose/lib/documentProvider.js +0 -30
- package/.output/server/node_modules/mongoose/lib/helpers/createJSONSchemaTypeDefinition.js +0 -24
- package/.output/server/node_modules/mongoose/lib/helpers/promiseOrCallback.js +0 -54
- package/.output/server/node_modules/mongoose/lib/plugins/validateBeforeSave.js +0 -51
- package/.output/server/node_modules/supports-color/index.js +0 -202
- package/.output/server/node_modules/supports-color/package.json +0 -64
|
@@ -21,6 +21,7 @@ const ValidationError = require('./error/validation');
|
|
|
21
21
|
const VersionError = require('./error/version');
|
|
22
22
|
const ParallelSaveError = require('./error/parallelSave');
|
|
23
23
|
const applyDefaultsHelper = require('./helpers/document/applyDefaults');
|
|
24
|
+
const isInPathsToSave = require('./helpers/document/isInPathsToSave');
|
|
24
25
|
const applyDefaultsToPOJO = require('./helpers/model/applyDefaultsToPOJO');
|
|
25
26
|
const applyEmbeddedDiscriminators = require('./helpers/discriminator/applyEmbeddedDiscriminators');
|
|
26
27
|
const applyHooks = require('./helpers/model/applyHooks');
|
|
@@ -50,6 +51,7 @@ const immediate = require('./helpers/immediate');
|
|
|
50
51
|
const internalToObjectOptions = require('./options').internalToObjectOptions;
|
|
51
52
|
const isDefaultIdIndex = require('./helpers/indexes/isDefaultIdIndex');
|
|
52
53
|
const isIndexEqual = require('./helpers/indexes/isIndexEqual');
|
|
54
|
+
const isIndexSpecEqual = require('./helpers/indexes/isIndexSpecEqual');
|
|
53
55
|
const isTimeseriesIndex = require('./helpers/indexes/isTimeseriesIndex');
|
|
54
56
|
const {
|
|
55
57
|
getRelatedDBIndexes,
|
|
@@ -59,10 +61,12 @@ const decorateDiscriminatorIndexOptions = require('./helpers/indexes/decorateDis
|
|
|
59
61
|
const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
|
|
60
62
|
const leanPopulateMap = require('./helpers/populate/leanPopulateMap');
|
|
61
63
|
const parallelLimit = require('./helpers/parallelLimit');
|
|
64
|
+
const parseProjection = require('./helpers/projection/parseProjection');
|
|
62
65
|
const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscriminatorPipeline');
|
|
63
66
|
const pushNestedArrayPaths = require('./helpers/model/pushNestedArrayPaths');
|
|
64
67
|
const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField');
|
|
65
68
|
const setDottedPath = require('./helpers/path/setDottedPath');
|
|
69
|
+
const { buildMiddlewareFilter } = require('./helpers/buildMiddlewareFilter');
|
|
66
70
|
const util = require('util');
|
|
67
71
|
const utils = require('./utils');
|
|
68
72
|
const minimize = require('./helpers/minimize');
|
|
@@ -71,7 +75,11 @@ const ObjectExpectedError = require('./error/objectExpected');
|
|
|
71
75
|
const decorateBulkWriteResult = require('./helpers/model/decorateBulkWriteResult');
|
|
72
76
|
const modelCollectionSymbol = Symbol('mongoose#Model#collection');
|
|
73
77
|
const modelDbSymbol = Symbol('mongoose#Model#db');
|
|
74
|
-
const
|
|
78
|
+
const {
|
|
79
|
+
arrayAtomicsBackupSymbol,
|
|
80
|
+
arrayAtomicsSymbol,
|
|
81
|
+
modelSymbol
|
|
82
|
+
} = require('./helpers/symbols');
|
|
75
83
|
const subclassedSymbol = Symbol('mongoose#Model#subclassed');
|
|
76
84
|
|
|
77
85
|
const { VERSION_INC, VERSION_WHERE, VERSION_ALL } = Document;
|
|
@@ -102,9 +110,11 @@ const saveToObjectOptions = Object.assign({}, internalToObjectOptions, {
|
|
|
102
110
|
* // You also use a model to create queries:
|
|
103
111
|
* const userFromDb = await UserModel.findOne({ name: 'Foo' });
|
|
104
112
|
*
|
|
105
|
-
* @param {
|
|
106
|
-
* @param {
|
|
107
|
-
* @param {
|
|
113
|
+
* @param {object} doc values for initial set
|
|
114
|
+
* @param {object} [fields] optional object containing the fields that were selected in the query which returned this document. You do **not** need to set this parameter to ensure Mongoose handles your [query projection](https://mongoosejs.com/docs/api/query.html#Query.prototype.select()).
|
|
115
|
+
* @param {object} [options] optional object containing the options for the document.
|
|
116
|
+
* @param {boolean} [options.defaults=true] if `false`, skip applying default values to this document.
|
|
117
|
+
* @param {boolean} [options.skipId=false] By default, Mongoose document if one is not provided and the document's schema does not override Mongoose's default `_id`. Set `skipId` to `true` to skip this generation step.
|
|
108
118
|
* @inherits Document https://mongoosejs.com/docs/api/document.html
|
|
109
119
|
* @event `error`: If listening to this event, 'error' is emitted when a document was saved and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.
|
|
110
120
|
* @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.
|
|
@@ -113,7 +123,7 @@ const saveToObjectOptions = Object.assign({}, internalToObjectOptions, {
|
|
|
113
123
|
* @api public
|
|
114
124
|
*/
|
|
115
125
|
|
|
116
|
-
function Model(doc, fields,
|
|
126
|
+
function Model(doc, fields, options) {
|
|
117
127
|
if (fields instanceof Schema) {
|
|
118
128
|
throw new TypeError('2nd argument to `Model` constructor must be a POJO or string, ' +
|
|
119
129
|
'**not** a schema. Make sure you\'re calling `mongoose.model()`, not ' +
|
|
@@ -124,7 +134,7 @@ function Model(doc, fields, skipId) {
|
|
|
124
134
|
'**not** a string. Make sure you\'re calling `mongoose.model()`, not ' +
|
|
125
135
|
'`mongoose.Model()`.');
|
|
126
136
|
}
|
|
127
|
-
Document.call(this, doc, fields,
|
|
137
|
+
Document.call(this, doc, fields, options);
|
|
128
138
|
}
|
|
129
139
|
|
|
130
140
|
/**
|
|
@@ -173,14 +183,17 @@ Model.prototype.db;
|
|
|
173
183
|
* If you use `useConnection()` to switch a model's connection, the model will still have the old connection's plugins.
|
|
174
184
|
*
|
|
175
185
|
* @function useConnection
|
|
176
|
-
* @param
|
|
177
|
-
* @return
|
|
186
|
+
* @param {Connection} connection The new connection to use
|
|
187
|
+
* @return {Model} this
|
|
178
188
|
* @api public
|
|
179
189
|
*/
|
|
180
190
|
|
|
181
191
|
Model.useConnection = function useConnection(connection) {
|
|
182
|
-
if (
|
|
183
|
-
throw new
|
|
192
|
+
if (typeof connection?.model !== 'function' || typeof connection.collection !== 'function' || typeof connection.base?.version !== 'string') {
|
|
193
|
+
throw new MongooseError('`useConnection()` requires a Mongoose connection.');
|
|
194
|
+
}
|
|
195
|
+
if (this.db?.base?.version && this.db?.base?.version !== connection.base?.version) {
|
|
196
|
+
throw new MongooseError(`The connection passed to \`useConnection()\` has a different version of Mongoose (${connection.base?.version}) than the model you are using (${this.db?.base?.version}).`);
|
|
184
197
|
}
|
|
185
198
|
if (this.db) {
|
|
186
199
|
delete this.db.models[this.modelName];
|
|
@@ -316,11 +329,10 @@ function _applyCustomWhere(doc, where) {
|
|
|
316
329
|
/*!
|
|
317
330
|
* ignore
|
|
318
331
|
*/
|
|
319
|
-
|
|
320
|
-
Model.prototype.$__handleSave = function(options, callback) {
|
|
332
|
+
function _createSaveOptions(doc, options) {
|
|
321
333
|
const saveOptions = {};
|
|
322
334
|
|
|
323
|
-
applyWriteConcern(
|
|
335
|
+
applyWriteConcern(doc.$__schema, options);
|
|
324
336
|
if (typeof options.writeConcern !== 'undefined') {
|
|
325
337
|
saveOptions.writeConcern = {};
|
|
326
338
|
if ('w' in options.writeConcern) {
|
|
@@ -347,211 +359,223 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
347
359
|
saveOptions.checkKeys = options.checkKeys;
|
|
348
360
|
}
|
|
349
361
|
|
|
350
|
-
const session =
|
|
351
|
-
const asyncLocalStorage =
|
|
362
|
+
const session = doc.$session();
|
|
363
|
+
const asyncLocalStorage = doc[modelDbSymbol].base.transactionAsyncLocalStorage?.getStore();
|
|
352
364
|
if (session != null) {
|
|
353
365
|
saveOptions.session = session;
|
|
354
366
|
} else if (!Object.hasOwn(options, 'session') && asyncLocalStorage?.session != null) {
|
|
355
367
|
// Only set session from asyncLocalStorage if `session` option wasn't originally passed in options
|
|
356
368
|
saveOptions.session = asyncLocalStorage.session;
|
|
357
369
|
}
|
|
358
|
-
if (this.$isNew) {
|
|
359
|
-
// send entire doc
|
|
360
|
-
const obj = this.toObject(saveToObjectOptions);
|
|
361
|
-
if ((obj || {})._id === void 0) {
|
|
362
|
-
// documents must have an _id else mongoose won't know
|
|
363
|
-
// what to update later if more changes are made. the user
|
|
364
|
-
// wouldn't know what _id was generated by mongodb either
|
|
365
|
-
// nor would the ObjectId generated by mongodb necessarily
|
|
366
|
-
// match the schema definition.
|
|
367
|
-
immediate(function() {
|
|
368
|
-
callback(new MongooseError('document must have an _id before saving'));
|
|
369
|
-
});
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
370
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
ret => callback(null, ret),
|
|
376
|
-
err => {
|
|
377
|
-
_setIsNew(this, true);
|
|
371
|
+
return saveOptions;
|
|
372
|
+
}
|
|
378
373
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
374
|
+
/*!
|
|
375
|
+
* ignore
|
|
376
|
+
*/
|
|
377
|
+
|
|
378
|
+
Model.prototype.$__save = async function $__save(options) {
|
|
379
|
+
try {
|
|
380
|
+
const hasValidateBeforeSaveOption = options &&
|
|
381
|
+
(typeof options === 'object') &&
|
|
382
|
+
('validateBeforeSave' in options);
|
|
383
|
+
const shouldValidateBeforeSave = hasValidateBeforeSaveOption ?
|
|
384
|
+
!!options.validateBeforeSave :
|
|
385
|
+
this.$__schema.options.validateBeforeSave;
|
|
386
|
+
if (shouldValidateBeforeSave) {
|
|
387
|
+
const hasValidateModifiedOnlyOption = options != null &&
|
|
388
|
+
typeof options === 'object' &&
|
|
389
|
+
Object.hasOwn(options, 'validateModifiedOnly');
|
|
390
|
+
const validateOptions = hasValidateModifiedOnlyOption ?
|
|
391
|
+
{ validateModifiedOnly: options.validateModifiedOnly } :
|
|
392
|
+
null;
|
|
393
|
+
await this.$validate(validateOptions);
|
|
394
|
+
this.$op = 'save';
|
|
395
|
+
}
|
|
382
396
|
|
|
383
|
-
this
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
this.$__.inserting = true;
|
|
397
|
+
await this._execDocumentPreHooks('save', options, [options]);
|
|
398
|
+
} catch (error) {
|
|
399
|
+
await this._execDocumentPostHooks('save', options, error);
|
|
387
400
|
return;
|
|
388
401
|
}
|
|
389
402
|
|
|
390
|
-
// Make sure we don't treat it as a new object on error,
|
|
391
|
-
// since it already exists
|
|
392
|
-
this.$__.inserting = false;
|
|
393
|
-
const delta = this.$__delta();
|
|
394
403
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
404
|
+
let result = null;
|
|
405
|
+
let where = null;
|
|
406
|
+
try {
|
|
407
|
+
const saveOptions = _createSaveOptions(this, options);
|
|
408
|
+
|
|
409
|
+
if (this.$isNew) {
|
|
410
|
+
// send entire doc
|
|
411
|
+
const obj = this.$__hasOnlyPrimitiveValues() ?
|
|
412
|
+
this.$__toObjectShallow() :
|
|
413
|
+
this.toObject(saveToObjectOptions);
|
|
414
|
+
if ((obj || {})._id === void 0) {
|
|
415
|
+
// documents must have an _id else mongoose won't know
|
|
416
|
+
// what to update later if more changes are made. the user
|
|
417
|
+
// wouldn't know what _id was generated by mongodb either
|
|
418
|
+
// nor would the ObjectId generated by mongodb necessarily
|
|
419
|
+
// match the schema definition.
|
|
420
|
+
throw new MongooseError('document must have an _id before saving');
|
|
403
421
|
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
if (delta) {
|
|
407
|
-
if (delta instanceof MongooseError) {
|
|
408
|
-
callback(delta);
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
422
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
423
|
+
this.$__version(true, obj);
|
|
424
|
+
this.$__reset();
|
|
425
|
+
_setIsNew(this, false);
|
|
426
|
+
// Make it possible to retry the insert
|
|
427
|
+
this.$__.inserting = true;
|
|
428
|
+
result = await this[modelCollectionSymbol].insertOne(obj, saveOptions).catch(err => {
|
|
429
|
+
_setIsNew(this, true);
|
|
430
|
+
throw err;
|
|
431
|
+
});
|
|
432
|
+
} else {
|
|
433
|
+
// Make sure we don't treat it as a new object on error,
|
|
434
|
+
// since it already exists
|
|
435
|
+
this.$__.inserting = false;
|
|
436
|
+
const pathsToSave = Array.isArray(options.pathsToSave) ? options.pathsToSave : null;
|
|
437
|
+
const pathsToSaveSet = pathsToSave != null ? new Set(pathsToSave) : null;
|
|
438
|
+
const delta = this.$__delta(pathsToSave, pathsToSaveSet);
|
|
439
|
+
const unsavedDirty = pathsToSave != null ? (delta != null ? delta[2] : this.$__dirty()) : null;
|
|
440
|
+
const unsavedDefaultPaths = pathsToSave != null
|
|
441
|
+
? Object.keys(this.$__.activePaths.getStatePaths('default')).filter(path => !isInPathsToSave(path, pathsToSaveSet, pathsToSave))
|
|
442
|
+
: null;
|
|
443
|
+
|
|
444
|
+
if (delta) {
|
|
445
|
+
where = this.$__where(delta[0]);
|
|
446
|
+
_applyCustomWhere(this, where);
|
|
447
|
+
|
|
448
|
+
const update = delta[1];
|
|
449
|
+
if (this.$__schema.options.minimize) {
|
|
450
|
+
for (const updateOp of Object.values(update)) {
|
|
451
|
+
if (updateOp == null) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
for (const key of Object.keys(updateOp)) {
|
|
455
|
+
if (updateOp[key] == null || typeof updateOp[key] !== 'object') {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
if (!utils.isPOJO(updateOp[key])) {
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
minimize(updateOp[key]);
|
|
462
|
+
if (utils.hasOwnKeys(updateOp[key]) === false) {
|
|
463
|
+
delete updateOp[key];
|
|
464
|
+
update.$unset = update.$unset || {};
|
|
465
|
+
update.$unset[key] = 1;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
438
468
|
}
|
|
439
469
|
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
470
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
471
|
+
// store the modified paths before the document is reset
|
|
472
|
+
this.$__.modifiedPaths = this.modifiedPaths();
|
|
473
|
+
this.$__reset();
|
|
474
|
+
restoreUnsavedState(this, unsavedDirty, unsavedDefaultPaths);
|
|
475
|
+
|
|
476
|
+
_setIsNew(this, false);
|
|
477
|
+
result = await this[modelCollectionSymbol].updateOne(where, update, saveOptions).catch(err => {
|
|
478
|
+
this.$__undoReset();
|
|
479
|
+
throw err;
|
|
480
|
+
});
|
|
481
|
+
} else {
|
|
482
|
+
where = this.$__where();
|
|
483
|
+
_applyCustomWhere(this, where);
|
|
484
|
+
if (this.$__.version) {
|
|
485
|
+
this.$__version(where, delta);
|
|
449
486
|
}
|
|
450
|
-
callback(null, ret);
|
|
451
|
-
},
|
|
452
|
-
err => {
|
|
453
|
-
this.$__undoReset();
|
|
454
487
|
|
|
455
|
-
|
|
488
|
+
applyReadConcern(this.$__schema, saveOptions);
|
|
489
|
+
result = await this.constructor.collection.findOne(where, { ...saveOptions, projection: { _id: 1 } })
|
|
490
|
+
.then(documentExists => ({ matchedCount: !documentExists ? 0 : 1 }));
|
|
456
491
|
}
|
|
457
|
-
|
|
458
|
-
}
|
|
459
|
-
|
|
492
|
+
}
|
|
493
|
+
} catch (err) {
|
|
494
|
+
const error = this.$__schema._transformDuplicateKeyError(err);
|
|
495
|
+
await this._execDocumentPostHooks('save', options, error);
|
|
460
496
|
return;
|
|
461
497
|
}
|
|
462
498
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
499
|
+
let numAffected = 0;
|
|
500
|
+
const writeConcern = options != null ?
|
|
501
|
+
options.writeConcern != null ?
|
|
502
|
+
options.writeConcern.w :
|
|
503
|
+
options.w :
|
|
504
|
+
0;
|
|
505
|
+
if (writeConcern !== 0) {
|
|
506
|
+
// Skip checking if write succeeded if writeConcern is set to
|
|
507
|
+
// unacknowledged writes, because otherwise `numAffected` will always be 0
|
|
508
|
+
if (result != null) {
|
|
509
|
+
if (Array.isArray(result)) {
|
|
510
|
+
numAffected = result.length;
|
|
511
|
+
} else if (result.matchedCount != null) {
|
|
512
|
+
numAffected = result.matchedCount;
|
|
513
|
+
} else {
|
|
514
|
+
numAffected = result;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
468
517
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
518
|
+
const versionBump = this.$__.version;
|
|
519
|
+
// was this an update that required a version bump?
|
|
520
|
+
if (versionBump && !this.$__.inserting) {
|
|
521
|
+
const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
|
|
522
|
+
this.$__.version = undefined;
|
|
474
523
|
const key = this.$__schema.options.versionKey;
|
|
475
|
-
const
|
|
476
|
-
if (
|
|
477
|
-
|
|
524
|
+
const version = this.$__getValue(key) || 0;
|
|
525
|
+
if (numAffected <= 0) {
|
|
526
|
+
// the update failed. pass an error back
|
|
527
|
+
this.$__undoReset();
|
|
528
|
+
const err = this.$__.$versionError ||
|
|
529
|
+
new VersionError(this, version, this.$__.modifiedPaths);
|
|
530
|
+
await this._execDocumentPostHooks('save', options, err);
|
|
531
|
+
return;
|
|
478
532
|
}
|
|
479
|
-
}
|
|
480
533
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
534
|
+
// increment version if was successful
|
|
535
|
+
if (doIncrement) {
|
|
536
|
+
this.$__setValue(key, version + 1);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (result != null && numAffected <= 0) {
|
|
540
|
+
this.$__undoReset();
|
|
541
|
+
const error = new DocumentNotFoundError(where, this.constructor.modelName, numAffected, result);
|
|
542
|
+
await this._execDocumentPostHooks('save', options, error);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
488
545
|
}
|
|
546
|
+
this.$__.saving = undefined;
|
|
547
|
+
this.$__.savedState = {};
|
|
548
|
+
this.$emit('save', this, numAffected);
|
|
549
|
+
this.constructor.emit('save', this, numAffected);
|
|
550
|
+
await this._execDocumentPostHooks('save', options);
|
|
489
551
|
};
|
|
490
552
|
|
|
491
553
|
/*!
|
|
492
|
-
*
|
|
554
|
+
* Restores $__.activePaths state and any atomics for paths that failed
|
|
555
|
+
* to save.
|
|
556
|
+
*
|
|
557
|
+
* @param {Document} doc
|
|
558
|
+
* @param {object[]} unsavedDirty
|
|
559
|
+
* @param {string[]} unsavedDefaultPaths
|
|
493
560
|
*/
|
|
494
561
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
const hooks = this.$__schema.s.hooks;
|
|
500
|
-
return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
|
|
501
|
-
callback(error, this);
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
let numAffected = 0;
|
|
505
|
-
const writeConcern = options != null ?
|
|
506
|
-
options.writeConcern != null ?
|
|
507
|
-
options.writeConcern.w :
|
|
508
|
-
options.w :
|
|
509
|
-
0;
|
|
510
|
-
if (writeConcern !== 0) {
|
|
511
|
-
// Skip checking if write succeeded if writeConcern is set to
|
|
512
|
-
// unacknowledged writes, because otherwise `numAffected` will always be 0
|
|
513
|
-
if (result != null) {
|
|
514
|
-
if (Array.isArray(result)) {
|
|
515
|
-
numAffected = result.length;
|
|
516
|
-
} else if (result.matchedCount != null) {
|
|
517
|
-
numAffected = result.matchedCount;
|
|
518
|
-
} else {
|
|
519
|
-
numAffected = result;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
const versionBump = this.$__.version;
|
|
524
|
-
// was this an update that required a version bump?
|
|
525
|
-
if (versionBump && !this.$__.inserting) {
|
|
526
|
-
if (numAffected <= 0) {
|
|
527
|
-
const key = this.$__schema.options.versionKey;
|
|
528
|
-
const version = this.$__getValue(key) || 0;
|
|
529
|
-
// the update failed. pass an error back
|
|
530
|
-
this.$__undoReset();
|
|
531
|
-
const err = this.$__.$versionError ||
|
|
532
|
-
new VersionError(this, version, this.$__.modifiedPaths);
|
|
533
|
-
return callback(err, this);
|
|
534
|
-
}
|
|
562
|
+
function restoreUnsavedState(doc, unsavedDirty, unsavedDefaultPaths) {
|
|
563
|
+
if (unsavedDirty == null) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
535
566
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
this.constructor.modelName, numAffected, result);
|
|
542
|
-
const hooks = this.$__schema.s.hooks;
|
|
543
|
-
return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
|
|
544
|
-
callback(error, this);
|
|
545
|
-
});
|
|
546
|
-
}
|
|
567
|
+
for (const dirty of unsavedDirty) {
|
|
568
|
+
doc.$__.activePaths.modify(dirty.path);
|
|
569
|
+
if (dirty.value?.[arrayAtomicsBackupSymbol]) {
|
|
570
|
+
dirty.value[arrayAtomicsSymbol] = dirty.value[arrayAtomicsBackupSymbol];
|
|
571
|
+
dirty.value[arrayAtomicsBackupSymbol] = null;
|
|
547
572
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
for (const path of unsavedDefaultPaths) {
|
|
576
|
+
doc.$__.activePaths.default(path);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
555
579
|
|
|
556
580
|
/*!
|
|
557
581
|
* ignore
|
|
@@ -583,17 +607,20 @@ function generateVersionError(doc, modifiedPaths, defaultPaths) {
|
|
|
583
607
|
* const newProduct = await product.save();
|
|
584
608
|
* newProduct === product; // true
|
|
585
609
|
*
|
|
586
|
-
* @param {
|
|
610
|
+
* @param {object} [options] options optional options
|
|
587
611
|
* @param {Session} [options.session=null] the [session](https://www.mongodb.com/docs/manual/reference/server-sessions/) associated with this save operation. If not specified, defaults to the [document's associated session](https://mongoosejs.com/docs/api/document.html#Document.prototype.session()).
|
|
588
|
-
* @param {
|
|
589
|
-
* @param {
|
|
590
|
-
* @param {
|
|
591
|
-
* @param {
|
|
592
|
-
* @param {
|
|
593
|
-
* @param {
|
|
594
|
-
* @param {
|
|
595
|
-
* @param {
|
|
612
|
+
* @param {object} [options.safe] (DEPRECATED) overrides [schema's safe option](https://mongoosejs.com/docs/guide.html#safe). Use the `w` option instead.
|
|
613
|
+
* @param {boolean} [options.validateBeforeSave] set to false to save without validating.
|
|
614
|
+
* @param {boolean} [options.validateModifiedOnly=false] if `true`, Mongoose will only validate modified paths, as opposed to modified paths and `required` paths.
|
|
615
|
+
* @param {number|string} [options.w] set the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/#w-option). Overrides the [schema-level `writeConcern` option](https://mongoosejs.com/docs/guide.html#writeConcern)
|
|
616
|
+
* @param {boolean} [options.j] set to true for MongoDB to wait until this `save()` has been [journaled before resolving the returned promise](https://www.mongodb.com/docs/manual/reference/write-concern/#j-option). Overrides the [schema-level `writeConcern` option](https://mongoosejs.com/docs/guide.html#writeConcern)
|
|
617
|
+
* @param {number} [options.wtimeout] sets a [timeout for the write concern](https://www.mongodb.com/docs/manual/reference/write-concern/#wtimeout). Overrides the [schema-level `writeConcern` option](https://mongoosejs.com/docs/guide.html#writeConcern).
|
|
618
|
+
* @param {boolean} [options.checkKeys=true] the MongoDB driver prevents you from saving keys that start with '$' or contain '.' by default. Set this option to `false` to skip that check. See [restrictions on field names](https://docs.mongodb.com/manual/reference/limits/#mongodb-limit-Restrictions-on-Field-Names)
|
|
619
|
+
* @param {boolean} [options.timestamps=true] if `false` and [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this `save()`.
|
|
596
620
|
* @param {Array} [options.pathsToSave] An array of paths that tell mongoose to only validate and save the paths in `pathsToSave`.
|
|
621
|
+
* @param {boolean|object} [options.middleware=true] set to `false` to skip all user-defined middleware
|
|
622
|
+
* @param {boolean} [options.middleware.pre=true] set to `false` to skip only pre hooks
|
|
623
|
+
* @param {boolean} [options.middleware.post=true] set to `false` to skip only post hooks
|
|
597
624
|
* @throws {DocumentNotFoundError} if this [save updates an existing document](https://mongoosejs.com/docs/api/document.html#Document.prototype.isNew) but the document doesn't exist in the database. For example, you will get this error if the document is [deleted between when you retrieved the document and when you saved it](documents.html#updating).
|
|
598
625
|
* @return {Promise}
|
|
599
626
|
* @api public
|
|
@@ -611,7 +638,7 @@ Model.prototype.save = async function save(options) {
|
|
|
611
638
|
if (this.$__.saving) {
|
|
612
639
|
parallelSave = new ParallelSaveError(this);
|
|
613
640
|
} else {
|
|
614
|
-
this.$__.saving =
|
|
641
|
+
this.$__.saving = true;
|
|
615
642
|
}
|
|
616
643
|
|
|
617
644
|
options = new SaveOptions(options);
|
|
@@ -621,11 +648,13 @@ Model.prototype.save = async function save(options) {
|
|
|
621
648
|
if (this.$__.timestamps != null) {
|
|
622
649
|
options.timestamps = this.$__.timestamps;
|
|
623
650
|
}
|
|
624
|
-
this.$
|
|
625
|
-
this
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
651
|
+
if (!this.$isNew) {
|
|
652
|
+
this.$__.$versionError = generateVersionError(
|
|
653
|
+
this,
|
|
654
|
+
this.modifiedPaths(),
|
|
655
|
+
Object.keys(this.$__.activePaths.getStatePaths('default'))
|
|
656
|
+
);
|
|
657
|
+
}
|
|
629
658
|
|
|
630
659
|
if (parallelSave) {
|
|
631
660
|
this.$__handleReject(parallelSave);
|
|
@@ -634,20 +663,17 @@ Model.prototype.save = async function save(options) {
|
|
|
634
663
|
|
|
635
664
|
this.$__.saveOptions = options;
|
|
636
665
|
|
|
637
|
-
|
|
638
|
-
this.$__save(options
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
resolve();
|
|
649
|
-
});
|
|
650
|
-
});
|
|
666
|
+
try {
|
|
667
|
+
await this.$__save(options);
|
|
668
|
+
} catch (error) {
|
|
669
|
+
this.$__handleReject(error);
|
|
670
|
+
throw error;
|
|
671
|
+
} finally {
|
|
672
|
+
this.$__.saving = null;
|
|
673
|
+
this.$__.saveOptions = null;
|
|
674
|
+
this.$__.$versionError = null;
|
|
675
|
+
this.$op = null;
|
|
676
|
+
}
|
|
651
677
|
|
|
652
678
|
return this;
|
|
653
679
|
};
|
|
@@ -745,7 +771,7 @@ Model.prototype.$__where = function _where(where) {
|
|
|
745
771
|
}
|
|
746
772
|
|
|
747
773
|
if (this._doc._id === void 0) {
|
|
748
|
-
|
|
774
|
+
throw new MongooseError('No _id found on document!');
|
|
749
775
|
}
|
|
750
776
|
|
|
751
777
|
return where;
|
|
@@ -786,9 +812,6 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
786
812
|
|
|
787
813
|
const self = this;
|
|
788
814
|
const where = this.$__where();
|
|
789
|
-
if (where instanceof Error) {
|
|
790
|
-
throw where;
|
|
791
|
-
}
|
|
792
815
|
const query = self.constructor.deleteOne();
|
|
793
816
|
|
|
794
817
|
if (this.$session() != null) {
|
|
@@ -797,38 +820,37 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
797
820
|
}
|
|
798
821
|
}
|
|
799
822
|
|
|
823
|
+
const preFilter = buildMiddlewareFilter(options, 'pre');
|
|
824
|
+
const postFilter = buildMiddlewareFilter(options, 'post');
|
|
825
|
+
|
|
800
826
|
query.pre(async function queryPreDeleteOne() {
|
|
801
|
-
await
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
827
|
+
const res = await self.constructor._middleware.execPre('deleteOne', self, [self, options], { filter: preFilter });
|
|
828
|
+
// `self` is passed to pre hooks as argument for backwards compatibility, but that
|
|
829
|
+
// isn't the actual arguments passed to the wrapped function.
|
|
830
|
+
if (res[0] !== self || res[1] !== options) {
|
|
831
|
+
throw new MongooseError('Document deleteOne pre hooks cannot overwrite arguments');
|
|
832
|
+
}
|
|
833
|
+
query.deleteOne(where, options);
|
|
808
834
|
// Apply custom where conditions _after_ document deleteOne middleware for
|
|
809
835
|
// consistency with save() - sharding plugin needs to set $where
|
|
810
836
|
if (self.$where != null) {
|
|
811
837
|
this.where(self.$where);
|
|
812
838
|
}
|
|
839
|
+
return res;
|
|
813
840
|
});
|
|
814
|
-
query.pre(function callSubdocPreHooks(
|
|
815
|
-
|
|
816
|
-
subdoc.constructor._middleware.execPre('deleteOne', subdoc, [subdoc, options], cb);
|
|
817
|
-
}, cb);
|
|
841
|
+
query.pre(function callSubdocPreHooks() {
|
|
842
|
+
return Promise.all(self.$getAllSubdocs().map(subdoc => subdoc.constructor._middleware.execPre('deleteOne', subdoc, [subdoc], { filter: preFilter })));
|
|
818
843
|
});
|
|
819
|
-
query.pre(function skipIfAlreadyDeleted(
|
|
844
|
+
query.pre(function skipIfAlreadyDeleted() {
|
|
820
845
|
if (self.$__.isDeleted) {
|
|
821
|
-
|
|
846
|
+
throw new Kareem.skipWrappedFunction();
|
|
822
847
|
}
|
|
823
|
-
return cb();
|
|
824
848
|
});
|
|
825
|
-
query.post(function callSubdocPostHooks(
|
|
826
|
-
|
|
827
|
-
subdoc.constructor._middleware.execPost('deleteOne', subdoc, [subdoc], {}, cb);
|
|
828
|
-
}, cb);
|
|
849
|
+
query.post(function callSubdocPostHooks() {
|
|
850
|
+
return Promise.all(self.$getAllSubdocs().map(subdoc => subdoc.constructor._middleware.execPost('deleteOne', subdoc, [subdoc], { filter: postFilter })));
|
|
829
851
|
});
|
|
830
|
-
query.post(function queryPostDeleteOne(
|
|
831
|
-
self.constructor._middleware.execPost('deleteOne', self, [self], {}
|
|
852
|
+
query.post(function queryPostDeleteOne() {
|
|
853
|
+
return self.constructor._middleware.execPost('deleteOne', self, [self], { filter: postFilter });
|
|
832
854
|
});
|
|
833
855
|
query.transform(function setIsDeleted(result) {
|
|
834
856
|
if (result?.deletedCount > 0) {
|
|
@@ -850,7 +872,7 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
850
872
|
* doc.$model() === Tank; // true
|
|
851
873
|
* await doc.$model('User').findById(id);
|
|
852
874
|
*
|
|
853
|
-
* @param {
|
|
875
|
+
* @param {string} [name] model name
|
|
854
876
|
* @method $model
|
|
855
877
|
* @api public
|
|
856
878
|
* @return {Model}
|
|
@@ -873,7 +895,7 @@ Model.prototype.$model = function $model(name) {
|
|
|
873
895
|
* doc.$model() === Tank; // true
|
|
874
896
|
* await doc.$model('User').findById(id);
|
|
875
897
|
*
|
|
876
|
-
* @param {
|
|
898
|
+
* @param {string} [name] model name
|
|
877
899
|
* @method model
|
|
878
900
|
* @api public
|
|
879
901
|
* @return {Model}
|
|
@@ -900,8 +922,8 @@ Model.prototype.model = Model.prototype.$model;
|
|
|
900
922
|
*
|
|
901
923
|
* - `findOne()`
|
|
902
924
|
*
|
|
903
|
-
* @param {
|
|
904
|
-
* @param {
|
|
925
|
+
* @param {object} filter
|
|
926
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
905
927
|
* @return {Query}
|
|
906
928
|
*/
|
|
907
929
|
|
|
@@ -945,14 +967,14 @@ Model.exists = function exists(filter, options) {
|
|
|
945
967
|
* const Employee = Person.discriminator('Employee', employeeSchema, 'staff');
|
|
946
968
|
* new Employee().__t; // "staff" because of 3rd argument above
|
|
947
969
|
*
|
|
948
|
-
* @param {
|
|
970
|
+
* @param {string} name discriminator model name
|
|
949
971
|
* @param {Schema} schema discriminator model schema
|
|
950
|
-
* @param {
|
|
951
|
-
* @param {
|
|
952
|
-
* @param {
|
|
953
|
-
* @param {
|
|
954
|
-
* @param {
|
|
955
|
-
* @param {
|
|
972
|
+
* @param {object|string} [options] If string, same as `options.value`.
|
|
973
|
+
* @param {string} [options.value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
|
|
974
|
+
* @param {boolean} [options.clone=true] By default, `discriminator()` clones the given `schema`. Set to `false` to skip cloning.
|
|
975
|
+
* @param {boolean} [options.overwriteModels=false] by default, Mongoose does not allow you to define a discriminator with the same name as another discriminator. Set this to allow overwriting discriminators with the same name.
|
|
976
|
+
* @param {boolean} [options.mergeHooks=true] By default, Mongoose merges the base schema's hooks with the discriminator schema's hooks. Set this option to `false` to make Mongoose use the discriminator schema's hooks instead.
|
|
977
|
+
* @param {boolean} [options.mergePlugins=true] By default, Mongoose merges the base schema's plugins with the discriminator schema's plugins. Set this option to `false` to make Mongoose use the discriminator schema's plugins instead.
|
|
956
978
|
* @return {Model} The newly created discriminator model
|
|
957
979
|
* @api public
|
|
958
980
|
*/
|
|
@@ -1175,7 +1197,7 @@ Model.init = function init() {
|
|
|
1175
1197
|
* });
|
|
1176
1198
|
*
|
|
1177
1199
|
* @api public
|
|
1178
|
-
* @param {
|
|
1200
|
+
* @param {object} [options] see [MongoDB driver docs](https://mongodb.github.io/node-mongodb-native/7.0/classes/Db.html#createCollection)
|
|
1179
1201
|
* @returns {Promise}
|
|
1180
1202
|
*/
|
|
1181
1203
|
|
|
@@ -1185,37 +1207,32 @@ Model.createCollection = async function createCollection(options) {
|
|
|
1185
1207
|
throw new MongooseError('Model.createCollection() no longer accepts a callback');
|
|
1186
1208
|
}
|
|
1187
1209
|
|
|
1188
|
-
const
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1210
|
+
const preFilter = buildMiddlewareFilter(options, 'pre');
|
|
1211
|
+
const postFilter = buildMiddlewareFilter(options, 'post');
|
|
1212
|
+
|
|
1213
|
+
// Remove middleware option before passing to MongoDB
|
|
1214
|
+
if (options?.middleware != null) {
|
|
1215
|
+
options = { ...options };
|
|
1216
|
+
delete options.middleware;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
[options] = await this.hooks.execPre('createCollection', this, [options], { filter: preFilter }).catch(err => {
|
|
1220
|
+
if (err instanceof Kareem.skipWrappedFunction) {
|
|
1221
|
+
return [err];
|
|
1222
|
+
}
|
|
1223
|
+
throw err;
|
|
1198
1224
|
});
|
|
1199
1225
|
|
|
1200
|
-
const collectionOptions = this
|
|
1201
|
-
this.schema &&
|
|
1202
|
-
this.schema.options &&
|
|
1203
|
-
this.schema.options.collectionOptions;
|
|
1226
|
+
const collectionOptions = this?.schema?.options?.collectionOptions;
|
|
1204
1227
|
if (collectionOptions != null) {
|
|
1205
1228
|
options = Object.assign({}, collectionOptions, options);
|
|
1206
1229
|
}
|
|
1207
1230
|
|
|
1208
|
-
const schemaCollation = this
|
|
1209
|
-
this.schema &&
|
|
1210
|
-
this.schema.options &&
|
|
1211
|
-
this.schema.options.collation;
|
|
1231
|
+
const schemaCollation = this?.schema?.options?.collation;
|
|
1212
1232
|
if (schemaCollation != null) {
|
|
1213
1233
|
options = Object.assign({ collation: schemaCollation }, options);
|
|
1214
1234
|
}
|
|
1215
|
-
const capped = this
|
|
1216
|
-
this.schema &&
|
|
1217
|
-
this.schema.options &&
|
|
1218
|
-
this.schema.options.capped;
|
|
1235
|
+
const capped = this?.schema?.options?.capped;
|
|
1219
1236
|
if (capped != null) {
|
|
1220
1237
|
if (typeof capped === 'number') {
|
|
1221
1238
|
options = Object.assign({ capped: true, size: capped }, options);
|
|
@@ -1223,10 +1240,7 @@ Model.createCollection = async function createCollection(options) {
|
|
|
1223
1240
|
options = Object.assign({ capped: true }, capped, options);
|
|
1224
1241
|
}
|
|
1225
1242
|
}
|
|
1226
|
-
const timeseries = this
|
|
1227
|
-
this.schema &&
|
|
1228
|
-
this.schema.options &&
|
|
1229
|
-
this.schema.options.timeseries;
|
|
1243
|
+
const timeseries = this?.schema?.options?.timeseries;
|
|
1230
1244
|
if (timeseries != null) {
|
|
1231
1245
|
options = Object.assign({ timeseries }, options);
|
|
1232
1246
|
if (options.expireAfterSeconds != null) {
|
|
@@ -1241,40 +1255,22 @@ Model.createCollection = async function createCollection(options) {
|
|
|
1241
1255
|
}
|
|
1242
1256
|
}
|
|
1243
1257
|
|
|
1244
|
-
const clusteredIndex = this
|
|
1245
|
-
this.schema &&
|
|
1246
|
-
this.schema.options &&
|
|
1247
|
-
this.schema.options.clusteredIndex;
|
|
1258
|
+
const clusteredIndex = this?.schema?.options?.clusteredIndex;
|
|
1248
1259
|
if (clusteredIndex != null) {
|
|
1249
1260
|
options = Object.assign({ clusteredIndex: { ...clusteredIndex, unique: true } }, options);
|
|
1250
1261
|
}
|
|
1251
1262
|
|
|
1252
1263
|
try {
|
|
1253
|
-
if (!
|
|
1264
|
+
if (!(options instanceof Kareem.skipWrappedFunction)) {
|
|
1254
1265
|
await this.db.createCollection(this.$__collection.collectionName, options);
|
|
1255
1266
|
}
|
|
1256
1267
|
} catch (err) {
|
|
1257
1268
|
if (err != null && (err.name !== 'MongoServerError' || err.code !== 48)) {
|
|
1258
|
-
await
|
|
1259
|
-
const _opts = { error: err };
|
|
1260
|
-
this.hooks.execPost('createCollection', this, [null], _opts, (err) => {
|
|
1261
|
-
if (err != null) {
|
|
1262
|
-
return reject(err);
|
|
1263
|
-
}
|
|
1264
|
-
resolve();
|
|
1265
|
-
});
|
|
1266
|
-
});
|
|
1269
|
+
await this.hooks.execPost('createCollection', this, [null], { error: err, filter: postFilter });
|
|
1267
1270
|
}
|
|
1268
1271
|
}
|
|
1269
1272
|
|
|
1270
|
-
await
|
|
1271
|
-
this.hooks.execPost('createCollection', this, [this.$__collection], (err) => {
|
|
1272
|
-
if (err != null) {
|
|
1273
|
-
return reject(err);
|
|
1274
|
-
}
|
|
1275
|
-
resolve();
|
|
1276
|
-
});
|
|
1277
|
-
});
|
|
1273
|
+
await this.hooks.execPost('createCollection', this, [this.$__collection], { filter: postFilter });
|
|
1278
1274
|
|
|
1279
1275
|
return this.$__collection;
|
|
1280
1276
|
};
|
|
@@ -1307,9 +1303,8 @@ Model.createCollection = async function createCollection(options) {
|
|
|
1307
1303
|
* toDrop; // Array of strings containing names of indexes that `syncIndexes()` will drop
|
|
1308
1304
|
* toCreate; // Array of strings containing names of indexes that `syncIndexes()` will create
|
|
1309
1305
|
*
|
|
1310
|
-
* @param {
|
|
1311
|
-
* @param {
|
|
1312
|
-
* @param {Boolean} [options.hideIndexes=false] set to `true` to hide indexes instead of dropping. Requires MongoDB server 4.4 or higher
|
|
1306
|
+
* @param {object} [options] options to pass to `ensureIndexes()`
|
|
1307
|
+
* @param {boolean} [options.hideIndexes=false] set to `true` to hide indexes instead of dropping. Requires MongoDB server 4.4 or higher
|
|
1313
1308
|
* @return {Promise}
|
|
1314
1309
|
* @api public
|
|
1315
1310
|
*/
|
|
@@ -1353,9 +1348,9 @@ Model.syncIndexes = async function syncIndexes(options) {
|
|
|
1353
1348
|
* const Customer = mongoose.model('Customer', schema);
|
|
1354
1349
|
* await Customer.createSearchIndex({ name: 'test', definition: { mappings: { dynamic: true } } });
|
|
1355
1350
|
*
|
|
1356
|
-
* @param {
|
|
1357
|
-
* @param {
|
|
1358
|
-
* @param {
|
|
1351
|
+
* @param {object} description index options, including `name` and `definition`
|
|
1352
|
+
* @param {string} description.name
|
|
1353
|
+
* @param {object} description.definition
|
|
1359
1354
|
* @return {Promise}
|
|
1360
1355
|
* @api public
|
|
1361
1356
|
*/
|
|
@@ -1376,8 +1371,8 @@ Model.createSearchIndex = async function createSearchIndex(description) {
|
|
|
1376
1371
|
* const Customer = mongoose.model('Customer', schema);
|
|
1377
1372
|
* await Customer.updateSearchIndex('test', { mappings: { dynamic: true } });
|
|
1378
1373
|
*
|
|
1379
|
-
* @param {
|
|
1380
|
-
* @param {
|
|
1374
|
+
* @param {string} name
|
|
1375
|
+
* @param {object} definition
|
|
1381
1376
|
* @return {Promise}
|
|
1382
1377
|
* @api public
|
|
1383
1378
|
*/
|
|
@@ -1398,7 +1393,7 @@ Model.updateSearchIndex = async function updateSearchIndex(name, definition) {
|
|
|
1398
1393
|
* const Customer = mongoose.model('Customer', schema);
|
|
1399
1394
|
* await Customer.dropSearchIndex('test');
|
|
1400
1395
|
*
|
|
1401
|
-
* @param {
|
|
1396
|
+
* @param {string} name
|
|
1402
1397
|
* @return {Promise}
|
|
1403
1398
|
* @api public
|
|
1404
1399
|
*/
|
|
@@ -1421,7 +1416,7 @@ Model.dropSearchIndex = async function dropSearchIndex(name) {
|
|
|
1421
1416
|
* await Customer.createSearchIndex({ name: 'test', definition: { mappings: { dynamic: true } } });
|
|
1422
1417
|
* const res = await Customer.listSearchIndexes(); // Includes `[{ name: 'test' }]`
|
|
1423
1418
|
*
|
|
1424
|
-
* @param {
|
|
1419
|
+
* @param {object} [options]
|
|
1425
1420
|
* @return {Promise<Array>}
|
|
1426
1421
|
* @api public
|
|
1427
1422
|
*/
|
|
@@ -1443,9 +1438,9 @@ Model.listSearchIndexes = async function listSearchIndexes(options) {
|
|
|
1443
1438
|
* toDrop; // Array of strings containing names of indexes that `syncIndexes()` will drop
|
|
1444
1439
|
* toCreate; // Array of index specs containing the keys of indexes that `syncIndexes()` will create
|
|
1445
1440
|
*
|
|
1446
|
-
* @param {
|
|
1447
|
-
* @param {
|
|
1448
|
-
* @return {Promise<
|
|
1441
|
+
* @param {object} [options]
|
|
1442
|
+
* @param {boolean} [options.indexOptionsToCreate=false] If true, `toCreate` will include both the index spec and the index options, not just the index spec
|
|
1443
|
+
* @return {Promise<object>} contains the indexes that would be dropped in MongoDB and indexes that would be created in MongoDB as `{ toDrop: string[], toCreate: string[] }`.
|
|
1449
1444
|
*/
|
|
1450
1445
|
|
|
1451
1446
|
Model.diffIndexes = async function diffIndexes(options) {
|
|
@@ -1548,10 +1543,10 @@ function getIndexesToDrop(schema, schemaIndexes, dbIndexes) {
|
|
|
1548
1543
|
*
|
|
1549
1544
|
* The returned promise resolves to a list of the dropped indexes' names as an array
|
|
1550
1545
|
*
|
|
1551
|
-
* @param {
|
|
1552
|
-
* @param {
|
|
1553
|
-
* @param {
|
|
1554
|
-
* @return {Promise<
|
|
1546
|
+
* @param {object} [options]
|
|
1547
|
+
* @param {string[]} [options.toDrop] if specified, contains a list of index names to drop
|
|
1548
|
+
* @param {boolean} [options.hideIndexes=false] set to `true` to hide indexes instead of dropping. Requires MongoDB server 4.4 or higher
|
|
1549
|
+
* @return {Promise<string[]>} list of dropped or hidden index names
|
|
1555
1550
|
* @api public
|
|
1556
1551
|
*/
|
|
1557
1552
|
|
|
@@ -1562,7 +1557,7 @@ Model.cleanIndexes = async function cleanIndexes(options) {
|
|
|
1562
1557
|
}
|
|
1563
1558
|
const model = this;
|
|
1564
1559
|
|
|
1565
|
-
if (Array.isArray(options
|
|
1560
|
+
if (Array.isArray(options?.toDrop)) {
|
|
1566
1561
|
const res = await _dropIndexes(options.toDrop, model, options);
|
|
1567
1562
|
return res;
|
|
1568
1563
|
}
|
|
@@ -1577,7 +1572,7 @@ async function _dropIndexes(toDrop, model, options) {
|
|
|
1577
1572
|
}
|
|
1578
1573
|
|
|
1579
1574
|
const collection = model.$__collection;
|
|
1580
|
-
if (options
|
|
1575
|
+
if (options?.hideIndexes) {
|
|
1581
1576
|
await Promise.all(toDrop.map(indexName => {
|
|
1582
1577
|
return model.db.db.command({
|
|
1583
1578
|
collMod: collection.collectionName,
|
|
@@ -1637,7 +1632,7 @@ Model.listIndexes = async function listIndexes() {
|
|
|
1637
1632
|
*
|
|
1638
1633
|
* _NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution._
|
|
1639
1634
|
*
|
|
1640
|
-
* @param {
|
|
1635
|
+
* @param {object} [options] internal options
|
|
1641
1636
|
* @return {Promise}
|
|
1642
1637
|
* @api public
|
|
1643
1638
|
*/
|
|
@@ -1659,10 +1654,10 @@ Model.ensureIndexes = async function ensureIndexes(options) {
|
|
|
1659
1654
|
};
|
|
1660
1655
|
|
|
1661
1656
|
/**
|
|
1662
|
-
* Similar to `ensureIndexes()`, except for it uses the [`createIndex`](https://mongodb.github.io/node-mongodb-native/
|
|
1657
|
+
* Similar to `ensureIndexes()`, except for it uses the [`createIndex`](https://mongodb.github.io/node-mongodb-native/7.0/classes/Db.html#createIndex)
|
|
1663
1658
|
* function.
|
|
1664
1659
|
*
|
|
1665
|
-
* @param {
|
|
1660
|
+
* @param {object} [options] internal options
|
|
1666
1661
|
* @return {Promise}
|
|
1667
1662
|
* @api public
|
|
1668
1663
|
*/
|
|
@@ -1704,14 +1699,32 @@ function _ensureIndexes(model, options, callback) {
|
|
|
1704
1699
|
}
|
|
1705
1700
|
}
|
|
1706
1701
|
|
|
1702
|
+
// Check for duplicate index definitions (gh-15056)
|
|
1703
|
+
const seenIndexes = [];
|
|
1704
|
+
for (const index of indexes) {
|
|
1705
|
+
const fields = index[0];
|
|
1706
|
+
const indexOptions = index[1];
|
|
1707
|
+
if (indexOptions.name == null) {
|
|
1708
|
+
for (const existingIndex of seenIndexes) {
|
|
1709
|
+
if (existingIndex[1].name == null && isIndexSpecEqual(existingIndex[0], fields)) {
|
|
1710
|
+
utils.warn('mongoose: Duplicate schema index on ' + JSON.stringify(fields) +
|
|
1711
|
+
' for model "' + model.modelName + '". ' +
|
|
1712
|
+
'This is often due to declaring an index using both "index: true" and "schema.index()". ' +
|
|
1713
|
+
'Please remove the duplicate index definition.');
|
|
1714
|
+
break;
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
seenIndexes.push(index);
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1707
1721
|
if (!indexes.length) {
|
|
1708
1722
|
immediate(function() {
|
|
1709
1723
|
done();
|
|
1710
1724
|
});
|
|
1711
1725
|
return;
|
|
1712
1726
|
}
|
|
1713
|
-
// Indexes are created one-by-one
|
|
1714
|
-
// with background indexes.
|
|
1727
|
+
// Indexes are created one-by-one
|
|
1715
1728
|
|
|
1716
1729
|
const indexSingleDone = function(err, fields, options, name) {
|
|
1717
1730
|
model.emit('index-single-done', err, fields, options, name);
|
|
@@ -1763,10 +1776,6 @@ function _ensureIndexes(model, options, callback) {
|
|
|
1763
1776
|
|
|
1764
1777
|
indexSingleStart(indexFields, options);
|
|
1765
1778
|
|
|
1766
|
-
if ('background' in options) {
|
|
1767
|
-
indexOptions.background = options.background;
|
|
1768
|
-
}
|
|
1769
|
-
|
|
1770
1779
|
// Just in case `createIndex()` throws a sync error
|
|
1771
1780
|
let promise = null;
|
|
1772
1781
|
try {
|
|
@@ -1912,9 +1921,9 @@ Model.discriminators;
|
|
|
1912
1921
|
*
|
|
1913
1922
|
* Only translate arguments of object type anything else is returned raw
|
|
1914
1923
|
*
|
|
1915
|
-
* @param {
|
|
1916
|
-
* @param {
|
|
1917
|
-
* @return {
|
|
1924
|
+
* @param {object} fields fields/conditions that may contain aliased keys
|
|
1925
|
+
* @param {boolean} [errorOnDuplicates] if true, throw an error if there's both a key and an alias for that key in `fields`
|
|
1926
|
+
* @return {object} the translated 'pure' fields/conditions
|
|
1918
1927
|
*/
|
|
1919
1928
|
Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
|
|
1920
1929
|
_checkContext(this, 'translateAliases');
|
|
@@ -1926,7 +1935,7 @@ Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
|
|
|
1926
1935
|
let currentSchema = this.schema;
|
|
1927
1936
|
for (const i in fieldKeys) {
|
|
1928
1937
|
const name = fieldKeys[i];
|
|
1929
|
-
if (currentSchema
|
|
1938
|
+
if (currentSchema?.aliases[name]) {
|
|
1930
1939
|
alias = currentSchema.aliases[name];
|
|
1931
1940
|
if (errorOnDuplicates && alias in fields) {
|
|
1932
1941
|
throw new MongooseError(`Provided object has both field "${name}" and its alias "${alias}"`);
|
|
@@ -1940,7 +1949,7 @@ Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
|
|
|
1940
1949
|
}
|
|
1941
1950
|
|
|
1942
1951
|
// Check if aliased path is a schema
|
|
1943
|
-
if (currentSchema
|
|
1952
|
+
if (currentSchema?.paths[alias]) {
|
|
1944
1953
|
currentSchema = currentSchema.paths[alias].schema;
|
|
1945
1954
|
}
|
|
1946
1955
|
else
|
|
@@ -2010,9 +2019,9 @@ Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
|
|
|
2010
2019
|
* This function triggers `deleteOne` query hooks. Read the
|
|
2011
2020
|
* [middleware docs](https://mongoosejs.com/docs/middleware.html#naming) to learn more.
|
|
2012
2021
|
*
|
|
2013
|
-
* @param {
|
|
2014
|
-
* @param {
|
|
2015
|
-
* @param {
|
|
2022
|
+
* @param {object} conditions
|
|
2023
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2024
|
+
* @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.
|
|
2016
2025
|
* @return {Query}
|
|
2017
2026
|
* @api public
|
|
2018
2027
|
*/
|
|
@@ -2043,9 +2052,9 @@ Model.deleteOne = function deleteOne(conditions, options) {
|
|
|
2043
2052
|
* This function triggers `deleteMany` query hooks. Read the
|
|
2044
2053
|
* [middleware docs](https://mongoosejs.com/docs/middleware.html#naming) to learn more.
|
|
2045
2054
|
*
|
|
2046
|
-
* @param {
|
|
2047
|
-
* @param {
|
|
2048
|
-
* @param {
|
|
2055
|
+
* @param {object} conditions
|
|
2056
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2057
|
+
* @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.
|
|
2049
2058
|
* @return {Query}
|
|
2050
2059
|
* @api public
|
|
2051
2060
|
*/
|
|
@@ -2084,10 +2093,10 @@ Model.deleteMany = function deleteMany(conditions, options) {
|
|
|
2084
2093
|
* // passing options
|
|
2085
2094
|
* await MyModel.find({ name: /john/i }, null, { skip: 10 }).exec();
|
|
2086
2095
|
*
|
|
2087
|
-
* @param {
|
|
2088
|
-
* @param {
|
|
2089
|
-
* @param {
|
|
2090
|
-
* @param {
|
|
2096
|
+
* @param {object|ObjectId} filter
|
|
2097
|
+
* @param {object|string|string[]} [projection] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
|
|
2098
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2099
|
+
* @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.
|
|
2091
2100
|
* @return {Query}
|
|
2092
2101
|
* @see field selection https://mongoosejs.com/docs/api/query.html#Query.prototype.select()
|
|
2093
2102
|
* @see query casting https://mongoosejs.com/docs/tutorials/query_casting.html
|
|
@@ -2124,9 +2133,9 @@ Model.find = function find(conditions, projection, options) {
|
|
|
2124
2133
|
* // select only the adventures name and length
|
|
2125
2134
|
* await Adventure.findById(id, 'name length').exec();
|
|
2126
2135
|
*
|
|
2127
|
-
* @param {
|
|
2128
|
-
* @param {
|
|
2129
|
-
* @param {
|
|
2136
|
+
* @param {any} id value of `_id` to query by
|
|
2137
|
+
* @param {object|string|string[]} [projection] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
|
|
2138
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2130
2139
|
* @return {Query}
|
|
2131
2140
|
* @see field selection https://mongoosejs.com/docs/api/query.html#Query.prototype.select()
|
|
2132
2141
|
* @see lean queries https://mongoosejs.com/docs/tutorials/lean.html
|
|
@@ -2162,10 +2171,10 @@ Model.findById = function findById(id, projection, options) {
|
|
|
2162
2171
|
* // Select only the adventures name and length
|
|
2163
2172
|
* await Adventure.findOne({ country: 'Croatia' }, 'name length').exec();
|
|
2164
2173
|
*
|
|
2165
|
-
* @param {
|
|
2166
|
-
* @param {
|
|
2167
|
-
* @param {
|
|
2168
|
-
* @param {
|
|
2174
|
+
* @param {object} [conditions]
|
|
2175
|
+
* @param {object|string|string[]} [projection] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
|
|
2176
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2177
|
+
* @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.
|
|
2169
2178
|
* @return {Query}
|
|
2170
2179
|
* @see field selection https://mongoosejs.com/docs/api/query.html#Query.prototype.select()
|
|
2171
2180
|
* @see lean queries https://mongoosejs.com/docs/tutorials/lean.html
|
|
@@ -2195,7 +2204,7 @@ Model.findOne = function findOne(conditions, projection, options) {
|
|
|
2195
2204
|
*
|
|
2196
2205
|
* const numAdventures = await Adventure.estimatedDocumentCount();
|
|
2197
2206
|
*
|
|
2198
|
-
* @param {
|
|
2207
|
+
* @param {object} [options]
|
|
2199
2208
|
* @return {Query}
|
|
2200
2209
|
* @api public
|
|
2201
2210
|
*/
|
|
@@ -2222,7 +2231,7 @@ Model.estimatedDocumentCount = function estimatedDocumentCount(options) {
|
|
|
2222
2231
|
* a full collection scan and **not** use any indexes.
|
|
2223
2232
|
*
|
|
2224
2233
|
* The `countDocuments()` function is similar to `count()`, but there are a
|
|
2225
|
-
* [few operators that `countDocuments()` does not support](https://mongodb.github.io/node-mongodb-native/
|
|
2234
|
+
* [few operators that `countDocuments()` does not support](https://mongodb.github.io/node-mongodb-native/7.0/classes/Collection.html#countDocuments).
|
|
2226
2235
|
* Below are the operators that `count()` supports but `countDocuments()` does not,
|
|
2227
2236
|
* and the suggested replacement:
|
|
2228
2237
|
*
|
|
@@ -2230,7 +2239,7 @@ Model.estimatedDocumentCount = function estimatedDocumentCount(options) {
|
|
|
2230
2239
|
* - `$near`: [`$geoWithin`](https://www.mongodb.com/docs/manual/reference/operator/query/geoWithin/) with [`$center`](https://www.mongodb.com/docs/manual/reference/operator/query/center/#op._S_center)
|
|
2231
2240
|
* - `$nearSphere`: [`$geoWithin`](https://www.mongodb.com/docs/manual/reference/operator/query/geoWithin/) with [`$centerSphere`](https://www.mongodb.com/docs/manual/reference/operator/query/centerSphere/#op._S_centerSphere)
|
|
2232
2241
|
*
|
|
2233
|
-
* @param {
|
|
2242
|
+
* @param {object} filter
|
|
2234
2243
|
* @return {Query}
|
|
2235
2244
|
* @api public
|
|
2236
2245
|
*/
|
|
@@ -2258,9 +2267,9 @@ Model.countDocuments = function countDocuments(conditions, options) {
|
|
|
2258
2267
|
* const query = Link.distinct('url');
|
|
2259
2268
|
* query.exec();
|
|
2260
2269
|
*
|
|
2261
|
-
* @param {
|
|
2262
|
-
* @param {
|
|
2263
|
-
* @param {
|
|
2270
|
+
* @param {string} field
|
|
2271
|
+
* @param {object} [conditions] optional
|
|
2272
|
+
* @param {object} [options] optional
|
|
2264
2273
|
* @return {Query}
|
|
2265
2274
|
* @api public
|
|
2266
2275
|
*/
|
|
@@ -2297,8 +2306,8 @@ Model.distinct = function distinct(field, conditions, options) {
|
|
|
2297
2306
|
* .where('name', /^b/i)
|
|
2298
2307
|
* ... etc
|
|
2299
2308
|
*
|
|
2300
|
-
* @param {
|
|
2301
|
-
* @param {
|
|
2309
|
+
* @param {string} path
|
|
2310
|
+
* @param {object} [val] optional value
|
|
2302
2311
|
* @return {Query}
|
|
2303
2312
|
* @api public
|
|
2304
2313
|
*/
|
|
@@ -2316,9 +2325,9 @@ Model.where = function where(path, val) {
|
|
|
2316
2325
|
*
|
|
2317
2326
|
* Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via `find({ $where: javascript })`, or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.
|
|
2318
2327
|
*
|
|
2319
|
-
* Blog.$where('this.username.indexOf("val") !== -1').exec(
|
|
2328
|
+
* const result = await Blog.$where('this.username.indexOf("val") !== -1').exec();
|
|
2320
2329
|
*
|
|
2321
|
-
* @param {
|
|
2330
|
+
* @param {string|Function} argument is a javascript string or anonymous function
|
|
2322
2331
|
* @method $where
|
|
2323
2332
|
* @memberOf Model
|
|
2324
2333
|
* @return {Query}
|
|
@@ -2373,25 +2382,25 @@ Model.$where = function $where() {
|
|
|
2373
2382
|
* doc.name = 'jason bourne';
|
|
2374
2383
|
* await doc.save();
|
|
2375
2384
|
*
|
|
2376
|
-
* @param {
|
|
2377
|
-
* @param {
|
|
2378
|
-
* @param {
|
|
2379
|
-
* @param {
|
|
2380
|
-
* @param {
|
|
2385
|
+
* @param {object} [conditions]
|
|
2386
|
+
* @param {object} [update]
|
|
2387
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2388
|
+
* @param {'before'|'after'} [options.returnDocument='before'] Has two possible values, `'before'` and `'after'`. By default, it will return the document before the update was applied.
|
|
2389
|
+
* @param {object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.lean()) and [the Mongoose lean tutorial](https://mongoosejs.com/docs/tutorials/lean.html).
|
|
2381
2390
|
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
|
|
2382
|
-
* @param {
|
|
2383
|
-
* @param {
|
|
2384
|
-
* @param {
|
|
2385
|
-
* @param {
|
|
2386
|
-
* @param {
|
|
2387
|
-
* @param {
|
|
2388
|
-
* @param {
|
|
2389
|
-
* @param {
|
|
2390
|
-
* @param {
|
|
2391
|
-
* @param {
|
|
2392
|
-
* @param {
|
|
2393
|
-
* @param {
|
|
2394
|
-
* @param {
|
|
2391
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
2392
|
+
* @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.
|
|
2393
|
+
* @param {boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
2394
|
+
* @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())
|
|
2395
|
+
* @param {boolean} [options.new=false] if true, return the modified document rather than the original
|
|
2396
|
+
* @param {object|string} [options.fields] Field selection. Equivalent to `.select(fields).findOneAndUpdate()`
|
|
2397
|
+
* @param {number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
|
|
2398
|
+
* @param {object|string} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
|
|
2399
|
+
* @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
|
|
2400
|
+
* @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
|
|
2401
|
+
* @param {boolean} [options.includeResultMetadata] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/7.0/interfaces/ModifyResult.html)
|
|
2402
|
+
* @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.
|
|
2403
|
+
* @param {boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
|
|
2395
2404
|
* @return {Query}
|
|
2396
2405
|
* @see Tutorial https://mongoosejs.com/docs/tutorials/findoneandupdate.html
|
|
2397
2406
|
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
|
|
@@ -2409,13 +2418,6 @@ Model.findOneAndUpdate = function(conditions, update, options) {
|
|
|
2409
2418
|
fields = options.fields || options.projection;
|
|
2410
2419
|
}
|
|
2411
2420
|
|
|
2412
|
-
update = clone(update, {
|
|
2413
|
-
depopulate: true,
|
|
2414
|
-
_isNested: true
|
|
2415
|
-
});
|
|
2416
|
-
|
|
2417
|
-
decorateUpdateWithVersionKey(update, options, this.schema.options.versionKey);
|
|
2418
|
-
|
|
2419
2421
|
const mq = new this.Query({}, {}, this, this.$__collection);
|
|
2420
2422
|
mq.select(fields);
|
|
2421
2423
|
|
|
@@ -2462,23 +2464,23 @@ Model.findOneAndUpdate = function(conditions, update, options) {
|
|
|
2462
2464
|
* doc.name = 'jason bourne';
|
|
2463
2465
|
* await doc.save();
|
|
2464
2466
|
*
|
|
2465
|
-
* @param {
|
|
2466
|
-
* @param {
|
|
2467
|
-
* @param {
|
|
2468
|
-
* @param {
|
|
2469
|
-
* @param {
|
|
2467
|
+
* @param {object|number|string} id value of `_id` to query by
|
|
2468
|
+
* @param {object} [update]
|
|
2469
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2470
|
+
* @param {'before'|'after'} [options.returnDocument='before'] Has two possible values, `'before'` and `'after'`. By default, it will return the document before the update was applied.
|
|
2471
|
+
* @param {object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.lean()) and [the Mongoose lean tutorial](https://mongoosejs.com/docs/tutorials/lean.html).
|
|
2470
2472
|
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
|
|
2471
|
-
* @param {
|
|
2472
|
-
* @param {
|
|
2473
|
-
* @param {
|
|
2474
|
-
* @param {
|
|
2475
|
-
* @param {
|
|
2476
|
-
* @param {
|
|
2477
|
-
* @param {
|
|
2478
|
-
* @param {
|
|
2479
|
-
* @param {
|
|
2480
|
-
* @param {
|
|
2481
|
-
* @param {
|
|
2473
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
2474
|
+
* @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.
|
|
2475
|
+
* @param {object|string} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
|
|
2476
|
+
* @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
|
|
2477
|
+
* @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
|
|
2478
|
+
* @param {boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/7.0/interfaces/ModifyResult.html) rather than just the document
|
|
2479
|
+
* @param {boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
2480
|
+
* @param {boolean} [options.new=false] if true, return the modified document rather than the original
|
|
2481
|
+
* @param {object|string} [options.select] sets the document fields to return.
|
|
2482
|
+
* @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.
|
|
2483
|
+
* @param {boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
|
|
2482
2484
|
* @return {Query}
|
|
2483
2485
|
* @see Model.findOneAndUpdate https://mongoosejs.com/docs/api/model.html#Model.findOneAndUpdate()
|
|
2484
2486
|
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
|
|
@@ -2524,16 +2526,16 @@ Model.findByIdAndUpdate = function(id, update, options) {
|
|
|
2524
2526
|
* doc.name = 'jason bourne';
|
|
2525
2527
|
* await doc.save();
|
|
2526
2528
|
*
|
|
2527
|
-
* @param {
|
|
2528
|
-
* @param {
|
|
2529
|
-
* @param {
|
|
2530
|
-
* @param {
|
|
2529
|
+
* @param {object} conditions
|
|
2530
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2531
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
2532
|
+
* @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())
|
|
2531
2533
|
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
|
|
2532
|
-
* @param {
|
|
2533
|
-
* @param {
|
|
2534
|
-
* @param {
|
|
2535
|
-
* @param {
|
|
2536
|
-
* @param {
|
|
2534
|
+
* @param {boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/7.0/interfaces/ModifyResult.html) rather than just the document
|
|
2535
|
+
* @param {object|string} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
|
|
2536
|
+
* @param {object|string} [options.select] sets the document fields to return.
|
|
2537
|
+
* @param {number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
|
|
2538
|
+
* @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.
|
|
2537
2539
|
* @return {Query}
|
|
2538
2540
|
* @api public
|
|
2539
2541
|
*/
|
|
@@ -2566,10 +2568,10 @@ Model.findOneAndDelete = function(conditions, options) {
|
|
|
2566
2568
|
*
|
|
2567
2569
|
* - `findOneAndDelete()`
|
|
2568
2570
|
*
|
|
2569
|
-
* @param {
|
|
2570
|
-
* @param {
|
|
2571
|
-
* @param {
|
|
2572
|
-
* @param {
|
|
2571
|
+
* @param {object|number|string} id value of `_id` to query by
|
|
2572
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2573
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
2574
|
+
* @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.
|
|
2573
2575
|
* @return {Query}
|
|
2574
2576
|
* @see Model.findOneAndDelete https://mongoosejs.com/docs/api/model.html#Model.findOneAndDelete()
|
|
2575
2577
|
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
|
|
@@ -2600,20 +2602,20 @@ Model.findByIdAndDelete = function(id, options) {
|
|
|
2600
2602
|
* A.findOneAndReplace(filter, replacement) // returns Query
|
|
2601
2603
|
* A.findOneAndReplace() // returns Query
|
|
2602
2604
|
*
|
|
2603
|
-
* @param {
|
|
2604
|
-
* @param {
|
|
2605
|
-
* @param {
|
|
2606
|
-
* @param {
|
|
2607
|
-
* @param {
|
|
2605
|
+
* @param {object} filter Replace the first document that matches this filter
|
|
2606
|
+
* @param {object} [replacement] Replace with this document
|
|
2607
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
2608
|
+
* @param {'before'|'after'} [options.returnDocument='before'] Has two possible values, `'before'` and `'after'`. By default, it will return the document before the update was applied.
|
|
2609
|
+
* @param {object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.lean()) and [the Mongoose lean tutorial](https://mongoosejs.com/docs/tutorials/lean.html).
|
|
2608
2610
|
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
|
|
2609
|
-
* @param {
|
|
2610
|
-
* @param {
|
|
2611
|
-
* @param {
|
|
2612
|
-
* @param {
|
|
2613
|
-
* @param {
|
|
2614
|
-
* @param {
|
|
2615
|
-
* @param {
|
|
2616
|
-
* @param {
|
|
2611
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
2612
|
+
* @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.
|
|
2613
|
+
* @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())
|
|
2614
|
+
* @param {object|string} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
|
|
2615
|
+
* @param {boolean} [options.includeResultMetadata] if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/7.0/interfaces/ModifyResult.html) rather than just the document
|
|
2616
|
+
* @param {object|string} [options.select] sets the document fields to return.
|
|
2617
|
+
* @param {number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
|
|
2618
|
+
* @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.
|
|
2617
2619
|
* @return {Query}
|
|
2618
2620
|
* @api public
|
|
2619
2621
|
*/
|
|
@@ -2659,10 +2661,10 @@ Model.findOneAndReplace = function(filter, replacement, options) {
|
|
|
2659
2661
|
* // specify options.
|
|
2660
2662
|
* await Character.create([{ name: 'Jean-Luc Picard' }], { session });
|
|
2661
2663
|
*
|
|
2662
|
-
* @param {Array|
|
|
2663
|
-
* @param {
|
|
2664
|
-
* @param {
|
|
2665
|
-
* @param {
|
|
2664
|
+
* @param {Array|object} docs Documents to insert, as a spread or array
|
|
2665
|
+
* @param {object} [options] Options passed down to `save()`. To specify `options`, `docs` **must** be an array, not a spread. See [Model.save](https://mongoosejs.com/docs/api/model.html#Model.prototype.save()) for available options.
|
|
2666
|
+
* @param {boolean} [options.ordered] saves the docs in series rather than parallel.
|
|
2667
|
+
* @param {boolean} [options.aggregateErrors] Aggregate Errors instead of throwing the first one that occurs. Default: false
|
|
2666
2668
|
* @return {Promise}
|
|
2667
2669
|
* @api public
|
|
2668
2670
|
*/
|
|
@@ -2727,6 +2729,26 @@ Model.create = async function create(doc, options) {
|
|
|
2727
2729
|
throw new MongooseError('Cannot call `create()` with a session and multiple documents unless `ordered: true` is set');
|
|
2728
2730
|
}
|
|
2729
2731
|
|
|
2732
|
+
if (!Array.isArray(doc) && args.length === 1) {
|
|
2733
|
+
let toSave = doc;
|
|
2734
|
+
|
|
2735
|
+
const Model = this.discriminators && doc[discriminatorKey] != null ?
|
|
2736
|
+
this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :
|
|
2737
|
+
this;
|
|
2738
|
+
if (Model == null) {
|
|
2739
|
+
throw new MongooseError(`Discriminator "${doc[discriminatorKey]}" not ` +
|
|
2740
|
+
`found for model "${this.modelName}"`);
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
if (!(toSave instanceof Model)) {
|
|
2744
|
+
toSave = new Model(toSave);
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
await toSave.$save(options);
|
|
2748
|
+
|
|
2749
|
+
return toSave;
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2730
2752
|
if (options.ordered) {
|
|
2731
2753
|
for (let i = 0; i < args.length; i++) {
|
|
2732
2754
|
try {
|
|
@@ -2805,11 +2827,6 @@ Model.create = async function create(doc, options) {
|
|
|
2805
2827
|
}
|
|
2806
2828
|
}
|
|
2807
2829
|
|
|
2808
|
-
|
|
2809
|
-
if (!Array.isArray(doc) && args.length === 1) {
|
|
2810
|
-
return res[0];
|
|
2811
|
-
}
|
|
2812
|
-
|
|
2813
2830
|
return res;
|
|
2814
2831
|
};
|
|
2815
2832
|
|
|
@@ -2831,8 +2848,8 @@ Model.create = async function create(doc, options) {
|
|
|
2831
2848
|
* // Create a new character within a transaction.
|
|
2832
2849
|
* await Character.insertOne({ name: 'Jean-Luc Picard' }, { session });
|
|
2833
2850
|
*
|
|
2834
|
-
* @param {
|
|
2835
|
-
* @param {
|
|
2851
|
+
* @param {object|Document} doc Document to insert, as a POJO or Mongoose document
|
|
2852
|
+
* @param {object} [options] Options passed down to `save()`.
|
|
2836
2853
|
* @return {Promise<Document>} resolves to the saved document
|
|
2837
2854
|
* @api public
|
|
2838
2855
|
*/
|
|
@@ -2840,6 +2857,10 @@ Model.create = async function create(doc, options) {
|
|
|
2840
2857
|
Model.insertOne = async function insertOne(doc, options) {
|
|
2841
2858
|
_checkContext(this, 'insertOne');
|
|
2842
2859
|
|
|
2860
|
+
if (doc == null || typeof doc !== 'object') {
|
|
2861
|
+
throw new ObjectParameterError(doc, 'doc', 'insertOne');
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2843
2864
|
const discriminatorKey = this.schema.options.discriminatorKey;
|
|
2844
2865
|
const Model = this.discriminators && doc[discriminatorKey] != null ?
|
|
2845
2866
|
this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :
|
|
@@ -2883,8 +2904,8 @@ Model.insertOne = async function insertOne(doc, options) {
|
|
|
2883
2904
|
* await doc.deleteOne();
|
|
2884
2905
|
*
|
|
2885
2906
|
* @param {Array} [pipeline]
|
|
2886
|
-
* @param {
|
|
2887
|
-
* @param {
|
|
2907
|
+
* @param {object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/7.0/classes/Collection.html#watch)
|
|
2908
|
+
* @param {boolean} [options.hydrate=false] if true and `fullDocument: 'updateLookup'` is set, Mongoose will automatically hydrate `fullDocument` into a fully fledged Mongoose document
|
|
2888
2909
|
* @return {ChangeStream} mongoose-specific change stream wrapper, inherits from EventEmitter
|
|
2889
2910
|
* @api public
|
|
2890
2911
|
*/
|
|
@@ -2892,27 +2913,21 @@ Model.insertOne = async function insertOne(doc, options) {
|
|
|
2892
2913
|
Model.watch = function(pipeline, options) {
|
|
2893
2914
|
_checkContext(this, 'watch');
|
|
2894
2915
|
|
|
2895
|
-
const changeStreamThunk = cb => {
|
|
2896
|
-
pipeline = pipeline || [];
|
|
2897
|
-
prepareDiscriminatorPipeline(pipeline, this.schema, 'fullDocument');
|
|
2898
|
-
if (this.$__collection.buffer) {
|
|
2899
|
-
this.$__collection.addQueue(() => {
|
|
2900
|
-
if (this.closed) {
|
|
2901
|
-
return;
|
|
2902
|
-
}
|
|
2903
|
-
const driverChangeStream = this.$__collection.watch(pipeline, options);
|
|
2904
|
-
cb(null, driverChangeStream);
|
|
2905
|
-
});
|
|
2906
|
-
} else {
|
|
2907
|
-
const driverChangeStream = this.$__collection.watch(pipeline, options);
|
|
2908
|
-
cb(null, driverChangeStream);
|
|
2909
|
-
}
|
|
2910
|
-
};
|
|
2911
|
-
|
|
2912
2916
|
options = options || {};
|
|
2917
|
+
const watchOptions = options?.hydrate !== undefined ?
|
|
2918
|
+
utils.omit(options, ['hydrate']) :
|
|
2919
|
+
{ ...options };
|
|
2913
2920
|
options.model = this;
|
|
2914
2921
|
|
|
2915
|
-
|
|
2922
|
+
|
|
2923
|
+
pipeline = pipeline || [];
|
|
2924
|
+
prepareDiscriminatorPipeline(pipeline, this.schema, 'fullDocument');
|
|
2925
|
+
|
|
2926
|
+
const changeStreamPromise = this.db._waitForConnect().then(
|
|
2927
|
+
() => this.$__collection.watch(pipeline, watchOptions)
|
|
2928
|
+
);
|
|
2929
|
+
|
|
2930
|
+
return new ChangeStream(changeStreamPromise, pipeline, options);
|
|
2916
2931
|
};
|
|
2917
2932
|
|
|
2918
2933
|
/**
|
|
@@ -2935,8 +2950,8 @@ Model.watch = function(pipeline, options) {
|
|
|
2935
2950
|
* // secondary that is experiencing replication lag.
|
|
2936
2951
|
* doc = await Person.findOne({ name: 'Ned Stark' }, null, { session, readPreference: 'secondary' });
|
|
2937
2952
|
*
|
|
2938
|
-
* @param {
|
|
2939
|
-
* @param {
|
|
2953
|
+
* @param {object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/7.0/classes/MongoClient.html#startSession)
|
|
2954
|
+
* @param {boolean} [options.causalConsistency=true] set to false to disable causal consistency
|
|
2940
2955
|
* @return {Promise<ClientSession>} promise that resolves to a MongoDB driver `ClientSession`
|
|
2941
2956
|
* @api public
|
|
2942
2957
|
*/
|
|
@@ -2978,14 +2993,17 @@ Model.startSession = function() {
|
|
|
2978
2993
|
* { name: 'The Empire Strikes Back' }
|
|
2979
2994
|
* ], { rawResult: true });
|
|
2980
2995
|
*
|
|
2981
|
-
* @param {Array|
|
|
2982
|
-
* @param {
|
|
2983
|
-
* @param {
|
|
2984
|
-
* @param {
|
|
2985
|
-
* @param {
|
|
2986
|
-
* @param {
|
|
2987
|
-
* @param {
|
|
2988
|
-
* @param {
|
|
2996
|
+
* @param {Array|object|any} doc(s)
|
|
2997
|
+
* @param {object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/7.0/classes/Collection.html#insertMany)
|
|
2998
|
+
* @param {boolean} [options.ordered=true] if true, will fail fast on the first error encountered. If false, will insert all the documents it can and report errors later. An `insertMany()` with `ordered = false` is called an "unordered" `insertMany()`.
|
|
2999
|
+
* @param {boolean} [options.rawResult=false] if false, the returned promise resolves to the documents that passed mongoose document validation. If `true`, will return the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/7.0/interfaces/InsertManyResult.html) with a `mongoose` property that contains `validationErrors` and `results` if this is an unordered `insertMany`.
|
|
3000
|
+
* @param {boolean} [options.lean=false] if `true`, skips hydrating the documents. This means Mongoose will **not** cast, validate, or apply defaults to any of the documents passed to `insertMany()`. This option is useful if you need the extra performance, but comes with data integrity risk. Consider using with [`castObject()`](https://mongoosejs.com/docs/api/model.html#Model.castObject()) and [`applyDefaults()`](https://mongoosejs.com/docs/api/model.html#Model.applyDefaults()).
|
|
3001
|
+
* @param {number} [options.limit=null] this limits the number of documents being processed (validation/casting) by mongoose in parallel, this does **NOT** send the documents in batches to MongoDB. Use this option if you're processing a large number of documents and your app is running out of memory.
|
|
3002
|
+
* @param {string|object|Array} [options.populate=null] populates the result documents. This option is a no-op if `rawResult` is set.
|
|
3003
|
+
* @param {boolean} [options.throwOnValidationError=false] If true and `ordered: false`, throw an error if one of the operations failed validation, but all valid operations completed successfully.
|
|
3004
|
+
* @param {boolean|object} [options.middleware=true] set to `false` to skip all user-defined middleware
|
|
3005
|
+
* @param {boolean} [options.middleware.pre=true] set to `false` to skip only pre hooks
|
|
3006
|
+
* @param {boolean} [options.middleware.post=true] set to `false` to skip only post hooks
|
|
2989
3007
|
* @return {Promise} resolving to the raw result from the MongoDB driver if `options.rawResult` was `true`, or the documents that passed validation, otherwise
|
|
2990
3008
|
* @api public
|
|
2991
3009
|
*/
|
|
@@ -2997,37 +3015,16 @@ Model.insertMany = async function insertMany(arr, options) {
|
|
|
2997
3015
|
throw new MongooseError('Model.insertMany() no longer accepts a callback');
|
|
2998
3016
|
}
|
|
2999
3017
|
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
return reject(err);
|
|
3004
|
-
}
|
|
3005
|
-
resolve(res);
|
|
3006
|
-
});
|
|
3007
|
-
});
|
|
3008
|
-
};
|
|
3009
|
-
|
|
3010
|
-
/**
|
|
3011
|
-
* ignore
|
|
3012
|
-
*
|
|
3013
|
-
* @param {Array} arr
|
|
3014
|
-
* @param {Object} options
|
|
3015
|
-
* @param {Function} callback
|
|
3016
|
-
* @api private
|
|
3017
|
-
* @memberOf Model
|
|
3018
|
-
* @method $__insertMany
|
|
3019
|
-
* @static
|
|
3020
|
-
*/
|
|
3018
|
+
options = options || {};
|
|
3019
|
+
const preFilter = buildMiddlewareFilter(options, 'pre');
|
|
3020
|
+
const postFilter = buildMiddlewareFilter(options, 'post');
|
|
3021
3021
|
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
options = null;
|
|
3022
|
+
try {
|
|
3023
|
+
[arr] = await this._middleware.execPre('insertMany', this, [arr], { filter: preFilter });
|
|
3024
|
+
} catch (error) {
|
|
3025
|
+
await this._middleware.execPost('insertMany', this, [arr], { error, filter: postFilter });
|
|
3027
3026
|
}
|
|
3028
|
-
|
|
3029
|
-
callback = callback || utils.noop;
|
|
3030
|
-
options = options || {};
|
|
3027
|
+
const ThisModel = this;
|
|
3031
3028
|
const limit = options.limit || 1000;
|
|
3032
3029
|
const rawResult = !!options.rawResult;
|
|
3033
3030
|
const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
|
|
@@ -3046,238 +3043,213 @@ Model.$__insertMany = function(arr, options, callback) {
|
|
|
3046
3043
|
const validationErrors = [];
|
|
3047
3044
|
const validationErrorsToOriginalOrder = new Map();
|
|
3048
3045
|
const results = ordered ? null : new Array(arr.length);
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
let createdNewDoc = false;
|
|
3059
|
-
if (!(doc instanceof _this)) {
|
|
3060
|
-
if (doc != null && typeof doc !== 'object') {
|
|
3061
|
-
return callback(new ObjectParameterError(doc, 'arr.' + index, 'insertMany'));
|
|
3062
|
-
}
|
|
3063
|
-
try {
|
|
3064
|
-
doc = new _this(doc);
|
|
3065
|
-
createdNewDoc = true;
|
|
3066
|
-
} catch (err) {
|
|
3067
|
-
return callback(err);
|
|
3068
|
-
}
|
|
3046
|
+
async function validateDoc(doc, index) {
|
|
3047
|
+
// If option `lean` is set to true bypass validation and hydration
|
|
3048
|
+
if (lean) {
|
|
3049
|
+
return doc;
|
|
3050
|
+
}
|
|
3051
|
+
let createdNewDoc = false;
|
|
3052
|
+
if (!(doc instanceof ThisModel)) {
|
|
3053
|
+
if (doc != null && typeof doc !== 'object') {
|
|
3054
|
+
throw new ObjectParameterError(doc, 'arr.' + index, 'insertMany');
|
|
3069
3055
|
}
|
|
3056
|
+
doc = new ThisModel(doc);
|
|
3057
|
+
createdNewDoc = true;
|
|
3058
|
+
}
|
|
3070
3059
|
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
error => {
|
|
3084
|
-
if (ordered === false) {
|
|
3085
|
-
// Add index to validation error so users can identify which document failed
|
|
3086
|
-
error.index = index;
|
|
3087
|
-
validationErrors.push(error);
|
|
3088
|
-
validationErrorsToOriginalOrder.set(error, index);
|
|
3089
|
-
results[index] = error;
|
|
3090
|
-
return callback(null, null);
|
|
3091
|
-
}
|
|
3092
|
-
callback(error);
|
|
3060
|
+
if (options.session != null) {
|
|
3061
|
+
doc.$session(options.session);
|
|
3062
|
+
}
|
|
3063
|
+
return doc.$validate(createdNewDoc ? { _skipParallelValidateCheck: true } : null)
|
|
3064
|
+
.then(() => doc)
|
|
3065
|
+
.catch(error => {
|
|
3066
|
+
if (ordered === false) {
|
|
3067
|
+
error.index = index;
|
|
3068
|
+
validationErrors.push(error);
|
|
3069
|
+
validationErrorsToOriginalOrder.set(error, index);
|
|
3070
|
+
results[index] = error;
|
|
3071
|
+
return;
|
|
3093
3072
|
}
|
|
3094
|
-
|
|
3095
|
-
|
|
3073
|
+
throw error;
|
|
3074
|
+
});
|
|
3075
|
+
}
|
|
3096
3076
|
|
|
3097
|
-
parallelLimit(
|
|
3098
|
-
if (error) {
|
|
3099
|
-
callback(error, null);
|
|
3100
|
-
return;
|
|
3101
|
-
}
|
|
3077
|
+
const docs = await parallelLimit(arr, validateDoc, limit);
|
|
3102
3078
|
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3079
|
+
const originalDocIndex = new Map();
|
|
3080
|
+
const validDocIndexToOriginalIndex = new Map();
|
|
3081
|
+
for (let i = 0; i < docs.length; ++i) {
|
|
3082
|
+
originalDocIndex.set(docs[i], i);
|
|
3083
|
+
}
|
|
3108
3084
|
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3085
|
+
// We filter all failed pre-validations by removing nulls
|
|
3086
|
+
const docAttributes = docs.filter(function(doc) {
|
|
3087
|
+
return doc != null;
|
|
3088
|
+
});
|
|
3089
|
+
for (let i = 0; i < docAttributes.length; ++i) {
|
|
3090
|
+
validDocIndexToOriginalIndex.set(i, originalDocIndex.get(docAttributes[i]));
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
// Make sure validation errors are in the same order as the
|
|
3094
|
+
// original documents, so if both doc1 and doc2 both fail validation,
|
|
3095
|
+
// `Model.insertMany([doc1, doc2])` will always have doc1's validation
|
|
3096
|
+
// error before doc2's. Re: gh-12791.
|
|
3097
|
+
if (validationErrors.length > 0) {
|
|
3098
|
+
validationErrors.sort((err1, err2) => {
|
|
3099
|
+
return validationErrorsToOriginalOrder.get(err1) - validationErrorsToOriginalOrder.get(err2);
|
|
3112
3100
|
});
|
|
3113
|
-
|
|
3114
|
-
validDocIndexToOriginalIndex.set(i, originalDocIndex.get(docAttributes[i]));
|
|
3115
|
-
}
|
|
3101
|
+
}
|
|
3116
3102
|
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3103
|
+
// Quickly escape while there aren't any valid docAttributes
|
|
3104
|
+
if (docAttributes.length === 0) {
|
|
3105
|
+
if (throwOnValidationError) {
|
|
3106
|
+
throw new MongooseBulkWriteError(
|
|
3107
|
+
validationErrors,
|
|
3108
|
+
results,
|
|
3109
|
+
null,
|
|
3110
|
+
'insertMany'
|
|
3111
|
+
);
|
|
3125
3112
|
}
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
'insertMany'
|
|
3135
|
-
));
|
|
3136
|
-
}
|
|
3137
|
-
if (rawResult) {
|
|
3138
|
-
const res = {
|
|
3139
|
-
acknowledged: true,
|
|
3140
|
-
insertedCount: 0,
|
|
3141
|
-
insertedIds: {}
|
|
3142
|
-
};
|
|
3143
|
-
decorateBulkWriteResult(res, validationErrors, validationErrors);
|
|
3144
|
-
return callback(null, res);
|
|
3145
|
-
}
|
|
3146
|
-
callback(null, []);
|
|
3147
|
-
return;
|
|
3113
|
+
if (rawResult) {
|
|
3114
|
+
const res = {
|
|
3115
|
+
acknowledged: true,
|
|
3116
|
+
insertedCount: 0,
|
|
3117
|
+
insertedIds: {}
|
|
3118
|
+
};
|
|
3119
|
+
decorateBulkWriteResult(res, validationErrors, validationErrors);
|
|
3120
|
+
return res;
|
|
3148
3121
|
}
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
return doc
|
|
3161
|
-
}
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
res => {
|
|
3165
|
-
if (!lean) {
|
|
3166
|
-
for (const attribute of docAttributes) {
|
|
3167
|
-
attribute.$__reset();
|
|
3168
|
-
_setIsNew(attribute, false);
|
|
3169
|
-
}
|
|
3170
|
-
}
|
|
3122
|
+
return [];
|
|
3123
|
+
}
|
|
3124
|
+
const docObjects = lean ? docAttributes : docAttributes.map(function(doc) {
|
|
3125
|
+
if (doc.$__schema.options.versionKey) {
|
|
3126
|
+
doc[doc.$__schema.options.versionKey] = 0;
|
|
3127
|
+
}
|
|
3128
|
+
const shouldSetTimestamps = options?.timestamps !== false && doc.initializeTimestamps && (!doc.$__ || doc.$__.timestamps !== false);
|
|
3129
|
+
if (shouldSetTimestamps) {
|
|
3130
|
+
doc.initializeTimestamps(options?.timestamps);
|
|
3131
|
+
}
|
|
3132
|
+
if (doc.$__hasOnlyPrimitiveValues()) {
|
|
3133
|
+
return doc.$__toObjectShallow();
|
|
3134
|
+
}
|
|
3135
|
+
return doc.toObject(internalToObjectOptions);
|
|
3136
|
+
});
|
|
3171
3137
|
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
'insertMany'
|
|
3183
|
-
));
|
|
3184
|
-
}
|
|
3138
|
+
let res;
|
|
3139
|
+
try {
|
|
3140
|
+
res = await this.$__collection.insertMany(docObjects, options);
|
|
3141
|
+
} catch (error) {
|
|
3142
|
+
// `writeErrors` is a property reported by the MongoDB driver,
|
|
3143
|
+
// just not if there's only 1 error.
|
|
3144
|
+
if (error.writeErrors == null &&
|
|
3145
|
+
error.result?.result?.writeErrors != null) {
|
|
3146
|
+
error.writeErrors = error.result.result.writeErrors;
|
|
3147
|
+
}
|
|
3185
3148
|
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
if (results[i] === void 0) {
|
|
3190
|
-
results[i] = docs[i];
|
|
3191
|
-
}
|
|
3192
|
-
}
|
|
3149
|
+
// `insertedDocs` is a Mongoose-specific property
|
|
3150
|
+
const hasWriteErrors = error?.writeErrors;
|
|
3151
|
+
const erroredIndexes = new Set((error?.writeErrors || []).map(err => err.index));
|
|
3193
3152
|
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3153
|
+
if (error.writeErrors != null) {
|
|
3154
|
+
for (let i = 0; i < error.writeErrors.length; ++i) {
|
|
3155
|
+
const originalIndex = validDocIndexToOriginalIndex.get(error.writeErrors[i].index);
|
|
3156
|
+
error.writeErrors[i] = { ...error.writeErrors[i], index: originalIndex };
|
|
3157
|
+
if (!ordered) {
|
|
3158
|
+
results[originalIndex] = error.writeErrors[i];
|
|
3199
3159
|
}
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3200
3162
|
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
if (err != null) {
|
|
3206
|
-
err.insertedDocs = docAttributes;
|
|
3207
|
-
}
|
|
3208
|
-
throw err;
|
|
3209
|
-
}
|
|
3210
|
-
);
|
|
3163
|
+
if (!ordered) {
|
|
3164
|
+
for (let i = 0; i < results.length; ++i) {
|
|
3165
|
+
if (results[i] === void 0) {
|
|
3166
|
+
results[i] = docs[i];
|
|
3211
3167
|
}
|
|
3168
|
+
}
|
|
3212
3169
|
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
error => {
|
|
3216
|
-
// `writeErrors` is a property reported by the MongoDB driver,
|
|
3217
|
-
// just not if there's only 1 error.
|
|
3218
|
-
if (error.writeErrors == null &&
|
|
3219
|
-
(error.result && error.result.result && error.result.result.writeErrors) != null) {
|
|
3220
|
-
error.writeErrors = error.result.result.writeErrors;
|
|
3221
|
-
}
|
|
3170
|
+
error.results = results;
|
|
3171
|
+
}
|
|
3222
3172
|
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3173
|
+
let firstErroredIndex = -1;
|
|
3174
|
+
error.insertedDocs = docAttributes.
|
|
3175
|
+
filter((doc, i) => {
|
|
3176
|
+
const isErrored = !hasWriteErrors || erroredIndexes.has(i);
|
|
3226
3177
|
|
|
3227
|
-
if (
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
error.writeErrors[i] = { ...error.writeErrors[i], index: originalIndex };
|
|
3231
|
-
if (!ordered) {
|
|
3232
|
-
results[originalIndex] = error.writeErrors[i];
|
|
3233
|
-
}
|
|
3178
|
+
if (ordered) {
|
|
3179
|
+
if (firstErroredIndex > -1) {
|
|
3180
|
+
return i < firstErroredIndex;
|
|
3234
3181
|
}
|
|
3235
|
-
}
|
|
3236
3182
|
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
if (results[i] === void 0) {
|
|
3240
|
-
results[i] = docs[i];
|
|
3241
|
-
}
|
|
3183
|
+
if (isErrored) {
|
|
3184
|
+
firstErroredIndex = i;
|
|
3242
3185
|
}
|
|
3186
|
+
}
|
|
3243
3187
|
|
|
3244
|
-
|
|
3188
|
+
return !isErrored;
|
|
3189
|
+
}).
|
|
3190
|
+
map(function setIsNewForInsertedDoc(doc) {
|
|
3191
|
+
if (lean) {
|
|
3192
|
+
return doc;
|
|
3245
3193
|
}
|
|
3194
|
+
doc.$__reset();
|
|
3195
|
+
_setIsNew(doc, false);
|
|
3196
|
+
return doc;
|
|
3197
|
+
});
|
|
3246
3198
|
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
const isErrored = !hasWriteErrors || erroredIndexes.has(i);
|
|
3199
|
+
if (rawResult && ordered === false) {
|
|
3200
|
+
decorateBulkWriteResult(error, validationErrors, results);
|
|
3201
|
+
}
|
|
3251
3202
|
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
return i < firstErroredIndex;
|
|
3255
|
-
}
|
|
3203
|
+
await this._middleware.execPost('insertMany', this, [arr], { error, filter: postFilter });
|
|
3204
|
+
}
|
|
3256
3205
|
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3206
|
+
if (!lean) {
|
|
3207
|
+
for (const attribute of docAttributes) {
|
|
3208
|
+
attribute.$__reset();
|
|
3209
|
+
_setIsNew(attribute, false);
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3261
3212
|
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3213
|
+
if (ordered === false && throwOnValidationError && validationErrors.length > 0) {
|
|
3214
|
+
for (let i = 0; i < results.length; ++i) {
|
|
3215
|
+
if (results[i] === void 0) {
|
|
3216
|
+
results[i] = docs[i];
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
throw new MongooseBulkWriteError(
|
|
3220
|
+
validationErrors,
|
|
3221
|
+
results,
|
|
3222
|
+
res,
|
|
3223
|
+
'insertMany'
|
|
3224
|
+
);
|
|
3225
|
+
}
|
|
3272
3226
|
|
|
3273
|
-
|
|
3274
|
-
|
|
3227
|
+
if (rawResult) {
|
|
3228
|
+
if (ordered === false) {
|
|
3229
|
+
for (let i = 0; i < results.length; ++i) {
|
|
3230
|
+
if (results[i] === void 0) {
|
|
3231
|
+
results[i] = docs[i];
|
|
3275
3232
|
}
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
// Decorate with mongoose validation errors in case of unordered,
|
|
3236
|
+
// because then still do `insertMany()`
|
|
3237
|
+
decorateBulkWriteResult(res, validationErrors, results);
|
|
3238
|
+
}
|
|
3239
|
+
return res;
|
|
3240
|
+
}
|
|
3276
3241
|
|
|
3277
|
-
|
|
3242
|
+
if (options.populate != null) {
|
|
3243
|
+
return this.populate(docAttributes, options.populate).catch(err => {
|
|
3244
|
+
if (err != null) {
|
|
3245
|
+
err.insertedDocs = docAttributes;
|
|
3278
3246
|
}
|
|
3279
|
-
|
|
3280
|
-
|
|
3247
|
+
throw err;
|
|
3248
|
+
});
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
const [result] = await this._middleware.execPost('insertMany', this, [docAttributes], { filter: postFilter });
|
|
3252
|
+
return result;
|
|
3281
3253
|
};
|
|
3282
3254
|
|
|
3283
3255
|
/*!
|
|
@@ -3359,38 +3331,43 @@ function _setIsNew(doc, val) {
|
|
|
3359
3331
|
* - `replaceOne`
|
|
3360
3332
|
*
|
|
3361
3333
|
* @param {Array} ops
|
|
3362
|
-
* @param {
|
|
3363
|
-
* @param {
|
|
3364
|
-
* @param {
|
|
3365
|
-
* @param {
|
|
3366
|
-
* @param {
|
|
3367
|
-
* @param {
|
|
3368
|
-
* @param {
|
|
3334
|
+
* @param {object} [ops.insertOne.document] The document to insert
|
|
3335
|
+
* @param {object} [ops.insertOne.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3336
|
+
* @param {object} [ops.updateOne.filter] Update the first document that matches this filter
|
|
3337
|
+
* @param {object} [ops.updateOne.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
|
|
3338
|
+
* @param {boolean} [ops.updateOne.upsert=false] If true, insert a doc if none match
|
|
3339
|
+
* @param {boolean} [ops.updateOne.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3340
|
+
* @param {boolean} [ops.updateOne.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
|
|
3341
|
+
* @param {object} [ops.updateOne.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
|
|
3369
3342
|
* @param {Array} [ops.updateOne.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
|
|
3370
|
-
* @param {
|
|
3371
|
-
* @param {
|
|
3372
|
-
* @param {
|
|
3373
|
-
* @param {
|
|
3374
|
-
* @param {
|
|
3343
|
+
* @param {object} [ops.updateMany.filter] Update all the documents that match this filter
|
|
3344
|
+
* @param {object} [ops.updateMany.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
|
|
3345
|
+
* @param {boolean} [ops.updateMany.upsert=false] If true, insert a doc if no documents match `filter`
|
|
3346
|
+
* @param {boolean} [ops.updateMany.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3347
|
+
* @param {boolean} [ops.updateMany.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
|
|
3348
|
+
* @param {object} [ops.updateMany.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
|
|
3375
3349
|
* @param {Array} [ops.updateMany.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
|
|
3376
|
-
* @param {
|
|
3377
|
-
* @param {
|
|
3378
|
-
* @param {
|
|
3379
|
-
* @param {
|
|
3380
|
-
* @param {
|
|
3381
|
-
* @param {
|
|
3382
|
-
* @param {
|
|
3383
|
-
* @param {
|
|
3384
|
-
* @param {
|
|
3350
|
+
* @param {object} [ops.deleteOne.filter] Delete the first document that matches this filter
|
|
3351
|
+
* @param {object} [ops.deleteMany.filter] Delete all documents that match this filter
|
|
3352
|
+
* @param {object} [ops.replaceOne.filter] Replace the first document that matches this filter
|
|
3353
|
+
* @param {object} [ops.replaceOne.replacement] The replacement document
|
|
3354
|
+
* @param {boolean} [ops.replaceOne.upsert=false] If true, insert a doc if no documents match `filter`
|
|
3355
|
+
* @param {object} [ops.replaceOne.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3356
|
+
* @param {object} [options]
|
|
3357
|
+
* @param {boolean} [options.ordered=true] If true, execute writes in order and stop at the first error. If false, execute writes in parallel and continue until all writes have either succeeded or errored.
|
|
3358
|
+
* @param {boolean} [options.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to any operations. Can be overridden at the operation-level.
|
|
3385
3359
|
* @param {ClientSession} [options.session=null] The session associated with this bulk write. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
|
|
3386
|
-
* @param {
|
|
3360
|
+
* @param {string|number} [options.w=1] The [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/). See [`Query#w()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.w()) for more information.
|
|
3387
3361
|
* @param {number} [options.wtimeout=null] The [write concern timeout](https://www.mongodb.com/docs/manual/reference/write-concern/#wtimeout).
|
|
3388
|
-
* @param {
|
|
3389
|
-
* @param {
|
|
3390
|
-
* @param {
|
|
3391
|
-
* @param {
|
|
3392
|
-
* @param {
|
|
3393
|
-
* @
|
|
3362
|
+
* @param {boolean} [options.j=true] If false, disable [journal acknowledgement](https://www.mongodb.com/docs/manual/reference/write-concern/#j-option)
|
|
3363
|
+
* @param {boolean} [options.skipValidation=false] Set to true to skip Mongoose schema validation on bulk write operations. Mongoose currently runs validation on `insertOne` and `replaceOne` operations by default.
|
|
3364
|
+
* @param {boolean} [options.bypassDocumentValidation=false] If true, disable [MongoDB server-side schema validation](https://www.mongodb.com/docs/manual/core/schema-validation/) for all writes in this bulk.
|
|
3365
|
+
* @param {boolean} [options.throwOnValidationError=false] If true and `ordered: false`, throw an error if one of the operations failed validation, but all valid operations completed successfully. Note that Mongoose will still send all valid operations to the MongoDB server.
|
|
3366
|
+
* @param {boolean|"throw"} [options.strict=null] Overwrites the [`strict` option](https://mongoosejs.com/docs/guide.html#strict) on schema. If false, allows filtering and writing fields not defined in the schema for all writes in this bulk.
|
|
3367
|
+
* @param {boolean|object} [options.middleware=true] set to `false` to skip all user-defined middleware
|
|
3368
|
+
* @param {boolean} [options.middleware.pre=true] set to `false` to skip only pre hooks
|
|
3369
|
+
* @param {boolean} [options.middleware.post=true] set to `false` to skip only post hooks
|
|
3370
|
+
* @return {Promise} resolves to a [`BulkWriteOpResult`](https://mongodb.github.io/node-mongodb-native/7.0/classes/BulkWriteResult.html) if the operation succeeds
|
|
3394
3371
|
* @api public
|
|
3395
3372
|
*/
|
|
3396
3373
|
|
|
@@ -3402,21 +3379,21 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3402
3379
|
throw new MongooseError('Model.bulkWrite() no longer accepts a callback');
|
|
3403
3380
|
}
|
|
3404
3381
|
options = options || {};
|
|
3382
|
+
const preFilter = buildMiddlewareFilter(options, 'pre');
|
|
3383
|
+
const postFilter = buildMiddlewareFilter(options, 'post');
|
|
3405
3384
|
|
|
3406
|
-
|
|
3407
|
-
this.hooks.execPre('bulkWrite', this, [ops, options],
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
});
|
|
3416
|
-
});
|
|
3385
|
+
try {
|
|
3386
|
+
[ops, options] = await this.hooks.execPre('bulkWrite', this, [ops, options], { filter: preFilter });
|
|
3387
|
+
} catch (err) {
|
|
3388
|
+
if (err instanceof Kareem.skipWrappedFunction) {
|
|
3389
|
+
ops = err;
|
|
3390
|
+
} else {
|
|
3391
|
+
await this.hooks.execPost('bulkWrite', this, [null], { error: err, filter: postFilter });
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3417
3394
|
|
|
3418
|
-
if (
|
|
3419
|
-
return
|
|
3395
|
+
if (ops instanceof Kareem.skipWrappedFunction) {
|
|
3396
|
+
return ops.args[0];
|
|
3420
3397
|
}
|
|
3421
3398
|
|
|
3422
3399
|
const ordered = options.ordered == null ? true : options.ordered;
|
|
@@ -3450,15 +3427,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3450
3427
|
try {
|
|
3451
3428
|
res = await this.$__collection.bulkWrite(ops, options);
|
|
3452
3429
|
} catch (error) {
|
|
3453
|
-
await
|
|
3454
|
-
const _opts = { error: error };
|
|
3455
|
-
this.hooks.execPost('bulkWrite', this, [null], _opts, (err) => {
|
|
3456
|
-
if (err != null) {
|
|
3457
|
-
return reject(err);
|
|
3458
|
-
}
|
|
3459
|
-
resolve();
|
|
3460
|
-
});
|
|
3461
|
-
});
|
|
3430
|
+
await this.hooks.execPost('bulkWrite', this, [null], { error, filter: postFilter });
|
|
3462
3431
|
}
|
|
3463
3432
|
} else {
|
|
3464
3433
|
let validOpIndexes = [];
|
|
@@ -3490,7 +3459,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3490
3459
|
sort((v1, v2) => v1.index - v2.index).
|
|
3491
3460
|
map(v => v.error);
|
|
3492
3461
|
|
|
3493
|
-
const validOps = validOpIndexes.sort().map(index => ops[index]);
|
|
3462
|
+
const validOps = validOpIndexes.sort((a, b) => a - b).map(index => ops[index]);
|
|
3494
3463
|
|
|
3495
3464
|
if (validOps.length === 0) {
|
|
3496
3465
|
if (options.throwOnValidationError && validationErrors.length) {
|
|
@@ -3527,15 +3496,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3527
3496
|
decorateBulkWriteResult(error, validationErrors, results);
|
|
3528
3497
|
}
|
|
3529
3498
|
|
|
3530
|
-
await
|
|
3531
|
-
const _opts = { error: error };
|
|
3532
|
-
this.hooks.execPost('bulkWrite', this, [null], _opts, (err) => {
|
|
3533
|
-
if (err != null) {
|
|
3534
|
-
return reject(err);
|
|
3535
|
-
}
|
|
3536
|
-
resolve();
|
|
3537
|
-
});
|
|
3538
|
-
});
|
|
3499
|
+
await this.hooks.execPost('bulkWrite', this, [null], { error, filter: postFilter });
|
|
3539
3500
|
}
|
|
3540
3501
|
|
|
3541
3502
|
if (validationErrors.length > 0) {
|
|
@@ -3552,14 +3513,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3552
3513
|
}
|
|
3553
3514
|
}
|
|
3554
3515
|
|
|
3555
|
-
await
|
|
3556
|
-
this.hooks.execPost('bulkWrite', this, [res], (err) => {
|
|
3557
|
-
if (err != null) {
|
|
3558
|
-
return reject(err);
|
|
3559
|
-
}
|
|
3560
|
-
resolve();
|
|
3561
|
-
});
|
|
3562
|
-
});
|
|
3516
|
+
await this.hooks.execPost('bulkWrite', this, [res], { filter: postFilter });
|
|
3563
3517
|
|
|
3564
3518
|
return res;
|
|
3565
3519
|
};
|
|
@@ -3578,14 +3532,17 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3578
3532
|
*
|
|
3579
3533
|
* Note that `bulkSave()` will **not** throw an error if only some of the `save()` calls succeeded.
|
|
3580
3534
|
*
|
|
3581
|
-
* @param {
|
|
3582
|
-
* @param {
|
|
3583
|
-
* @param {
|
|
3535
|
+
* @param {Document[]} documents
|
|
3536
|
+
* @param {object} [options] options passed to the underlying `bulkWrite()`
|
|
3537
|
+
* @param {boolean} [options.timestamps] defaults to `null`, when set to false, mongoose will not add/update timestamps to the documents.
|
|
3584
3538
|
* @param {ClientSession} [options.session=null] The session associated with this bulk write. See [transactions docs](https://mongoosejs.com/docs/transactions.html).
|
|
3585
|
-
* @param {
|
|
3539
|
+
* @param {string|number} [options.w=1] The [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/). See [`Query#w()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.w()) for more information.
|
|
3586
3540
|
* @param {number} [options.wtimeout=null] The [write concern timeout](https://www.mongodb.com/docs/manual/reference/write-concern/#wtimeout).
|
|
3587
|
-
* @param {
|
|
3588
|
-
* @param {
|
|
3541
|
+
* @param {boolean} [options.j=true] If false, disable [journal acknowledgement](https://www.mongodb.com/docs/manual/reference/write-concern/#j-option)
|
|
3542
|
+
* @param {boolean} [options.validateBeforeSave=true] set to `false` to skip Mongoose validation on all documents
|
|
3543
|
+
* @param {boolean|object} [options.middleware=true] set to `false` to skip all user-defined middleware
|
|
3544
|
+
* @param {boolean} [options.middleware.pre=true] set to `false` to skip only pre hooks
|
|
3545
|
+
* @param {boolean} [options.middleware.post=true] set to `false` to skip only post hooks
|
|
3589
3546
|
* @return {BulkWriteResult} the return value from `bulkWrite()`
|
|
3590
3547
|
*/
|
|
3591
3548
|
Model.bulkSave = async function bulkSave(documents, options) {
|
|
@@ -3631,7 +3588,7 @@ Model.bulkSave = async function bulkSave(documents, options) {
|
|
|
3631
3588
|
const successfulDocuments = [];
|
|
3632
3589
|
for (let i = 0; i < documents.length; i++) {
|
|
3633
3590
|
const document = documents[i];
|
|
3634
|
-
const documentError = bulkWriteError
|
|
3591
|
+
const documentError = bulkWriteError?.writeErrors.find(writeError => {
|
|
3635
3592
|
const writeErrorDocumentId = writeError.err.op._id || writeError.err.op.q._id;
|
|
3636
3593
|
return writeErrorDocumentId.toString() === document._doc._id.toString();
|
|
3637
3594
|
});
|
|
@@ -3640,7 +3597,7 @@ Model.bulkSave = async function bulkSave(documents, options) {
|
|
|
3640
3597
|
successfulDocuments.push(document);
|
|
3641
3598
|
}
|
|
3642
3599
|
}
|
|
3643
|
-
await Promise.all(successfulDocuments.map(document => handleSuccessfulWrite(document)));
|
|
3600
|
+
await Promise.all(successfulDocuments.map(document => handleSuccessfulWrite(document, options)));
|
|
3644
3601
|
|
|
3645
3602
|
if (bulkWriteError != null) {
|
|
3646
3603
|
throw bulkWriteError;
|
|
@@ -3649,43 +3606,30 @@ Model.bulkSave = async function bulkSave(documents, options) {
|
|
|
3649
3606
|
return bulkWriteResult;
|
|
3650
3607
|
};
|
|
3651
3608
|
|
|
3652
|
-
function buildPreSavePromise(document, options) {
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
}
|
|
3659
|
-
resolve();
|
|
3660
|
-
});
|
|
3661
|
-
});
|
|
3609
|
+
async function buildPreSavePromise(document, options) {
|
|
3610
|
+
const preFilter = buildMiddlewareFilter(options, 'pre');
|
|
3611
|
+
const [newOptions] = await document.schema.s.hooks.execPre('save', document, [options], { filter: preFilter });
|
|
3612
|
+
if (newOptions !== options) {
|
|
3613
|
+
throw new MongooseError('Cannot overwrite options in pre("save") hook on bulkSave()');
|
|
3614
|
+
}
|
|
3662
3615
|
}
|
|
3663
3616
|
|
|
3664
|
-
function handleSuccessfulWrite(document) {
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
}
|
|
3669
|
-
|
|
3670
|
-
document.$__reset();
|
|
3671
|
-
document._applyVersionIncrement();
|
|
3672
|
-
|
|
3673
|
-
document.schema.s.hooks.execPost('save', document, [document], {}, (err) => {
|
|
3674
|
-
if (err) {
|
|
3675
|
-
reject(err);
|
|
3676
|
-
return;
|
|
3677
|
-
}
|
|
3678
|
-
resolve();
|
|
3679
|
-
});
|
|
3617
|
+
async function handleSuccessfulWrite(document, options) {
|
|
3618
|
+
if (document.$isNew) {
|
|
3619
|
+
_setIsNew(document, false);
|
|
3620
|
+
}
|
|
3680
3621
|
|
|
3681
|
-
|
|
3622
|
+
document.$__reset();
|
|
3623
|
+
document._applyVersionIncrement();
|
|
3624
|
+
const postFilter = buildMiddlewareFilter(options, 'post');
|
|
3625
|
+
return document.schema.s.hooks.execPost('save', document, [document], { filter: postFilter });
|
|
3682
3626
|
}
|
|
3683
3627
|
|
|
3684
3628
|
/**
|
|
3685
3629
|
* Apply defaults to the given document or POJO.
|
|
3686
3630
|
*
|
|
3687
|
-
* @param {
|
|
3688
|
-
* @returns {
|
|
3631
|
+
* @param {object|Document} obj object or document to apply defaults on
|
|
3632
|
+
* @returns {object|Document}
|
|
3689
3633
|
* @api public
|
|
3690
3634
|
*/
|
|
3691
3635
|
|
|
@@ -3722,9 +3666,9 @@ Model.applyDefaults = function applyDefaults(doc) {
|
|
|
3722
3666
|
* obj.name; // 'John'
|
|
3723
3667
|
* obj.upper; // 'JOHN', Mongoose applied the return value of the virtual to the given object
|
|
3724
3668
|
*
|
|
3725
|
-
* @param {
|
|
3726
|
-
* @param {
|
|
3727
|
-
* @returns {
|
|
3669
|
+
* @param {object} obj object or document to apply virtuals on
|
|
3670
|
+
* @param {string[]} [virtualsToApply] optional whitelist of virtuals to apply
|
|
3671
|
+
* @returns {object} obj
|
|
3728
3672
|
* @api public
|
|
3729
3673
|
*/
|
|
3730
3674
|
|
|
@@ -3755,11 +3699,11 @@ Model.applyVirtuals = function applyVirtuals(obj, virtualsToApply) {
|
|
|
3755
3699
|
* obj.createdAt; // 2024-06-01T18:00:00.000Z
|
|
3756
3700
|
* obj.updatedAt; // 2024-06-01T18:00:00.000Z
|
|
3757
3701
|
*
|
|
3758
|
-
* @param {
|
|
3759
|
-
* @param {
|
|
3760
|
-
* @param {
|
|
3702
|
+
* @param {object} obj object or document to apply virtuals on
|
|
3703
|
+
* @param {object} [options]
|
|
3704
|
+
* @param {boolean} [options.isUpdate=false] if true, treat this as an update: just set updatedAt, skip setting createdAt. If false, set both createdAt and updatedAt
|
|
3761
3705
|
* @param {Function} [options.currentTime] if set, Mongoose will call this function to get the current time.
|
|
3762
|
-
* @returns {
|
|
3706
|
+
* @returns {object} obj
|
|
3763
3707
|
* @api public
|
|
3764
3708
|
*/
|
|
3765
3709
|
|
|
@@ -3789,10 +3733,10 @@ Model.applyTimestamps = function applyTimestamps(obj, options) {
|
|
|
3789
3733
|
*
|
|
3790
3734
|
* Test.castObject({ num: 'not a number' }); // Throws a ValidationError
|
|
3791
3735
|
*
|
|
3792
|
-
* @param {
|
|
3793
|
-
* @param {
|
|
3794
|
-
* @param {
|
|
3795
|
-
* @returns {
|
|
3736
|
+
* @param {object} obj object or document to cast
|
|
3737
|
+
* @param {object} options options passed to castObject
|
|
3738
|
+
* @param {boolean} options.ignoreCastErrors If set to `true` will not throw a ValidationError and only return values that were successfully cast.
|
|
3739
|
+
* @returns {object} POJO casted to the model's schema
|
|
3796
3740
|
* @throws {ValidationError} if casting failed for at least one path
|
|
3797
3741
|
* @api public
|
|
3798
3742
|
*/
|
|
@@ -3810,7 +3754,7 @@ Model.castObject = function castObject(obj, options) {
|
|
|
3810
3754
|
|
|
3811
3755
|
for (const path of paths) {
|
|
3812
3756
|
const schemaType = schema.path(path);
|
|
3813
|
-
if (!schemaType
|
|
3757
|
+
if (!schemaType?.$isMongooseArray) {
|
|
3814
3758
|
continue;
|
|
3815
3759
|
}
|
|
3816
3760
|
|
|
@@ -3851,7 +3795,7 @@ Model.castObject = function castObject(obj, options) {
|
|
|
3851
3795
|
}
|
|
3852
3796
|
} else {
|
|
3853
3797
|
cur[pieces[pieces.length - 1]] = [
|
|
3854
|
-
Model.castObject.call(schemaType.
|
|
3798
|
+
Model.castObject.call(schemaType.Constructor, val)
|
|
3855
3799
|
];
|
|
3856
3800
|
}
|
|
3857
3801
|
|
|
@@ -3860,7 +3804,7 @@ Model.castObject = function castObject(obj, options) {
|
|
|
3860
3804
|
}
|
|
3861
3805
|
if (schemaType.$isSingleNested || schemaType.$isMongooseDocumentArrayElement) {
|
|
3862
3806
|
try {
|
|
3863
|
-
val = Model.castObject.call(schemaType.
|
|
3807
|
+
val = Model.castObject.call(schemaType.Constructor, val);
|
|
3864
3808
|
} catch (err) {
|
|
3865
3809
|
if (!options.ignoreCastErrors) {
|
|
3866
3810
|
error = error || new ValidationError();
|
|
@@ -3896,17 +3840,17 @@ Model.castObject = function castObject(obj, options) {
|
|
|
3896
3840
|
/**
|
|
3897
3841
|
* Build bulk write operations for `bulkSave()`.
|
|
3898
3842
|
*
|
|
3899
|
-
* @param {
|
|
3900
|
-
* @param {
|
|
3901
|
-
* @param {
|
|
3902
|
-
* @param {
|
|
3903
|
-
* @return {
|
|
3843
|
+
* @param {Document[]} documents The array of documents to build write operations of
|
|
3844
|
+
* @param {object} options
|
|
3845
|
+
* @param {boolean} options.skipValidation defaults to `false`, when set to true, building the write operations will bypass validating the documents.
|
|
3846
|
+
* @param {boolean} options.timestamps defaults to `null`, when set to false, mongoose will not add/update timestamps to the documents.
|
|
3847
|
+
* @return {Promise[]} Returns a array of all Promises the function executes to be awaited.
|
|
3904
3848
|
* @api private
|
|
3905
3849
|
*/
|
|
3906
3850
|
|
|
3907
3851
|
Model.buildBulkWriteOperations = function buildBulkWriteOperations(documents, options) {
|
|
3908
3852
|
if (!Array.isArray(documents)) {
|
|
3909
|
-
throw new
|
|
3853
|
+
throw new MongooseError(`bulkSave expects an array of documents to be passed, received \`${documents}\` instead`);
|
|
3910
3854
|
}
|
|
3911
3855
|
|
|
3912
3856
|
setDefaultOptions();
|
|
@@ -3914,7 +3858,7 @@ Model.buildBulkWriteOperations = function buildBulkWriteOperations(documents, op
|
|
|
3914
3858
|
const writeOperations = documents.map((document, i) => {
|
|
3915
3859
|
if (!options.skipValidation) {
|
|
3916
3860
|
if (!(document instanceof Document)) {
|
|
3917
|
-
throw new
|
|
3861
|
+
throw new MongooseError(`documents.${i} was not a mongoose document, documents must be an array of mongoose documents (instanceof mongoose.Document).`);
|
|
3918
3862
|
}
|
|
3919
3863
|
if (options.validateBeforeSave == null || options.validateBeforeSave) {
|
|
3920
3864
|
const err = document.validateSync();
|
|
@@ -3981,18 +3925,18 @@ Model.buildBulkWriteOperations = function buildBulkWriteOperations(documents, op
|
|
|
3981
3925
|
* // hydrate previous data into a Mongoose document
|
|
3982
3926
|
* const mongooseCandy = Candy.hydrate({ _id: '54108337212ffb6d459f854c', type: 'jelly bean' });
|
|
3983
3927
|
*
|
|
3984
|
-
* @param {
|
|
3985
|
-
* @param {
|
|
3986
|
-
* @param {
|
|
3987
|
-
* @param {
|
|
3988
|
-
* @param {
|
|
3989
|
-
* @param {
|
|
3990
|
-
* @param {
|
|
3928
|
+
* @param {object} obj
|
|
3929
|
+
* @param {object|string|string[]} [projection] optional projection containing which fields should be selected for this document
|
|
3930
|
+
* @param {object} [options] optional options
|
|
3931
|
+
* @param {boolean} [options.setters=false] if true, apply schema setters when hydrating
|
|
3932
|
+
* @param {boolean} [options.hydratedPopulatedDocs=false] if true, populates the docs if passing pre-populated data
|
|
3933
|
+
* @param {boolean} [options.virtuals=false] if true, sets any virtuals present on `obj`
|
|
3934
|
+
* @param {boolean|'throw'} [options.strict=false] configure strict mode for the hydrated document. In particular, if strict is false, fields not in the schema won't be stripped out; if strict is 'throw', `hydrate()` will throw an error if there are any fields that are not in the schema. Defaults to true (silently strip out fields not in the schema).
|
|
3991
3935
|
* @return {Document} document instance
|
|
3992
3936
|
* @api public
|
|
3993
3937
|
*/
|
|
3994
3938
|
|
|
3995
|
-
Model.hydrate = function(obj, projection, options) {
|
|
3939
|
+
Model.hydrate = function hydrate(obj, projection, options) {
|
|
3996
3940
|
_checkContext(this, 'hydrate');
|
|
3997
3941
|
|
|
3998
3942
|
if (options?.virtuals && options?.hydratedPopulatedDocs === false) {
|
|
@@ -4000,9 +3944,10 @@ Model.hydrate = function(obj, projection, options) {
|
|
|
4000
3944
|
}
|
|
4001
3945
|
|
|
4002
3946
|
if (projection != null) {
|
|
4003
|
-
if (obj
|
|
3947
|
+
if (obj?.$__ != null) {
|
|
4004
3948
|
obj = obj.toObject(internalToObjectOptions);
|
|
4005
3949
|
}
|
|
3950
|
+
projection = parseProjection(projection);
|
|
4006
3951
|
obj = applyProjection(obj, projection);
|
|
4007
3952
|
}
|
|
4008
3953
|
const document = require('./queryHelpers').createModel(this, obj, projection, projection, options);
|
|
@@ -4035,19 +3980,19 @@ Model.hydrate = function(obj, projection, options) {
|
|
|
4035
3980
|
*
|
|
4036
3981
|
* - `updateMany()`
|
|
4037
3982
|
*
|
|
4038
|
-
* @param {
|
|
4039
|
-
* @param {
|
|
4040
|
-
* @param {
|
|
4041
|
-
* @param {
|
|
4042
|
-
* @param {
|
|
4043
|
-
* @param {
|
|
4044
|
-
* @param {
|
|
4045
|
-
* @param {
|
|
4046
|
-
* @param {
|
|
3983
|
+
* @param {object} filter
|
|
3984
|
+
* @param {object|Array} update. If array, this update will be treated as an update pipeline and not casted.
|
|
3985
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
3986
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
3987
|
+
* @param {boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
3988
|
+
* @param {object} [options.writeConcern=null] sets the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](https://mongoosejs.com/docs/guide.html#writeConcern)
|
|
3989
|
+
* @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. Does nothing if schema-level timestamps are not set.
|
|
3990
|
+
* @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.
|
|
3991
|
+
* @param {boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
|
|
4047
3992
|
* @return {Query}
|
|
4048
3993
|
* @see Query docs https://mongoosejs.com/docs/queries.html
|
|
4049
3994
|
* @see MongoDB docs https://www.mongodb.com/docs/manual/reference/command/update/#update-command-output
|
|
4050
|
-
* @see UpdateResult https://mongodb.github.io/node-mongodb-native/
|
|
3995
|
+
* @see UpdateResult https://mongodb.github.io/node-mongodb-native/7.0/interfaces/UpdateResult.html
|
|
4051
3996
|
* @api public
|
|
4052
3997
|
*/
|
|
4053
3998
|
|
|
@@ -4083,19 +4028,19 @@ Model.updateMany = function updateMany(conditions, update, options) {
|
|
|
4083
4028
|
*
|
|
4084
4029
|
* - `updateOne()`
|
|
4085
4030
|
*
|
|
4086
|
-
* @param {
|
|
4087
|
-
* @param {
|
|
4088
|
-
* @param {
|
|
4089
|
-
* @param {
|
|
4090
|
-
* @param {
|
|
4091
|
-
* @param {
|
|
4092
|
-
* @param {
|
|
4093
|
-
* @param {
|
|
4094
|
-
* @param {
|
|
4031
|
+
* @param {object} filter
|
|
4032
|
+
* @param {object|Array} update. If array, this update will be treated as an update pipeline and not casted.
|
|
4033
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
4034
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
4035
|
+
* @param {boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
4036
|
+
* @param {object} [options.writeConcern=null] sets the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](https://mongoosejs.com/docs/guide.html#writeConcern)
|
|
4037
|
+
* @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.
|
|
4038
|
+
* @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.
|
|
4039
|
+
* @param {boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
|
|
4095
4040
|
* @return {Query}
|
|
4096
4041
|
* @see Query docs https://mongoosejs.com/docs/queries.html
|
|
4097
4042
|
* @see MongoDB docs https://www.mongodb.com/docs/manual/reference/command/update/#update-command-output
|
|
4098
|
-
* @see UpdateResult https://mongodb.github.io/node-mongodb-native/
|
|
4043
|
+
* @see UpdateResult https://mongodb.github.io/node-mongodb-native/7.0/interfaces/UpdateResult.html
|
|
4099
4044
|
* @api public
|
|
4100
4045
|
*/
|
|
4101
4046
|
|
|
@@ -4121,17 +4066,17 @@ Model.updateOne = function updateOne(conditions, doc, options) {
|
|
|
4121
4066
|
*
|
|
4122
4067
|
* - `replaceOne()`
|
|
4123
4068
|
*
|
|
4124
|
-
* @param {
|
|
4125
|
-
* @param {
|
|
4126
|
-
* @param {
|
|
4127
|
-
* @param {
|
|
4128
|
-
* @param {
|
|
4129
|
-
* @param {
|
|
4130
|
-
* @param {
|
|
4131
|
-
* @param {
|
|
4069
|
+
* @param {object} filter
|
|
4070
|
+
* @param {object} doc
|
|
4071
|
+
* @param {object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
|
|
4072
|
+
* @param {boolean|'throw'} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
|
|
4073
|
+
* @param {boolean} [options.upsert=false] if true, and no documents found, insert a new document
|
|
4074
|
+
* @param {object} [options.writeConcern=null] sets the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](https://mongoosejs.com/docs/guide.html#writeConcern)
|
|
4075
|
+
* @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. Does nothing if schema-level timestamps are not set.
|
|
4076
|
+
* @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.
|
|
4132
4077
|
* @return {Query}
|
|
4133
4078
|
* @see Query docs https://mongoosejs.com/docs/queries.html
|
|
4134
|
-
* @see UpdateResult https://mongodb.github.io/node-mongodb-native/
|
|
4079
|
+
* @see UpdateResult https://mongodb.github.io/node-mongodb-native/7.0/interfaces/UpdateResult.html
|
|
4135
4080
|
* @return {Query}
|
|
4136
4081
|
* @api public
|
|
4137
4082
|
*/
|
|
@@ -4139,7 +4084,7 @@ Model.updateOne = function updateOne(conditions, doc, options) {
|
|
|
4139
4084
|
Model.replaceOne = function replaceOne(conditions, doc, options) {
|
|
4140
4085
|
_checkContext(this, 'replaceOne');
|
|
4141
4086
|
|
|
4142
|
-
const versionKey = this
|
|
4087
|
+
const versionKey = this?.schema?.options?.versionKey || null;
|
|
4143
4088
|
if (versionKey && !doc[versionKey]) {
|
|
4144
4089
|
doc[versionKey] = 0;
|
|
4145
4090
|
}
|
|
@@ -4165,10 +4110,7 @@ function _update(model, op, conditions, doc, options) {
|
|
|
4165
4110
|
}
|
|
4166
4111
|
options = typeof options === 'function' ? options : clone(options);
|
|
4167
4112
|
|
|
4168
|
-
const versionKey = model
|
|
4169
|
-
model.schema &&
|
|
4170
|
-
model.schema.options &&
|
|
4171
|
-
model.schema.options.versionKey || null;
|
|
4113
|
+
const versionKey = model?.schema?.options?.versionKey ?? null;
|
|
4172
4114
|
decorateUpdateWithVersionKey(doc, options, versionKey);
|
|
4173
4115
|
|
|
4174
4116
|
return mq[op](conditions, doc, options);
|
|
@@ -4214,7 +4156,7 @@ function _update(model, op, conditions, doc, options) {
|
|
|
4214
4156
|
* @see Aggregate https://mongoosejs.com/docs/api/aggregate.html#Aggregate()
|
|
4215
4157
|
* @see MongoDB https://www.mongodb.com/docs/manual/applications/aggregation/
|
|
4216
4158
|
* @param {Array} [pipeline] aggregation pipeline as an array of objects
|
|
4217
|
-
* @param {
|
|
4159
|
+
* @param {object} [options] aggregation options
|
|
4218
4160
|
* @return {Aggregate}
|
|
4219
4161
|
* @api public
|
|
4220
4162
|
*/
|
|
@@ -4253,10 +4195,10 @@ Model.aggregate = function aggregate(pipeline, options) {
|
|
|
4253
4195
|
* Object.keys(err.errors); // ['name']
|
|
4254
4196
|
* }
|
|
4255
4197
|
*
|
|
4256
|
-
* @param {
|
|
4257
|
-
* @param {
|
|
4258
|
-
* @param {
|
|
4259
|
-
* @return {Promise<
|
|
4198
|
+
* @param {object} obj
|
|
4199
|
+
* @param {object|Array|string} pathsOrOptions
|
|
4200
|
+
* @param {object} [context]
|
|
4201
|
+
* @return {Promise<object>} casted and validated copy of `obj` if validation succeeded
|
|
4260
4202
|
* @api public
|
|
4261
4203
|
*/
|
|
4262
4204
|
|
|
@@ -4307,7 +4249,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4307
4249
|
|
|
4308
4250
|
for (const path of paths) {
|
|
4309
4251
|
const schemaType = schema.path(path);
|
|
4310
|
-
if (!schemaType
|
|
4252
|
+
if (!schemaType?.$isMongooseArray || schemaType.$isMongooseDocumentArray) {
|
|
4311
4253
|
continue;
|
|
4312
4254
|
}
|
|
4313
4255
|
|
|
@@ -4327,51 +4269,34 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4327
4269
|
}
|
|
4328
4270
|
}
|
|
4329
4271
|
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
if (
|
|
4334
|
-
|
|
4272
|
+
const promises = [];
|
|
4273
|
+
for (const path of paths) {
|
|
4274
|
+
const schemaType = schema.path(path);
|
|
4275
|
+
if (schemaType == null) {
|
|
4276
|
+
continue;
|
|
4335
4277
|
}
|
|
4336
4278
|
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
continue;
|
|
4342
|
-
}
|
|
4343
|
-
|
|
4344
|
-
const pieces = path.indexOf('.') === -1 ? [path] : path.split('.');
|
|
4345
|
-
let cur = obj;
|
|
4346
|
-
for (let i = 0; i < pieces.length - 1; ++i) {
|
|
4347
|
-
cur = cur[pieces[i]];
|
|
4348
|
-
}
|
|
4349
|
-
|
|
4350
|
-
const val = get(obj, path, void 0);
|
|
4351
|
-
|
|
4352
|
-
schemaType.doValidate(val, err => {
|
|
4353
|
-
if (err) {
|
|
4354
|
-
error = error || new ValidationError();
|
|
4355
|
-
error.addError(path, err);
|
|
4356
|
-
}
|
|
4357
|
-
_checkDone();
|
|
4358
|
-
}, context, { path: path });
|
|
4279
|
+
const pieces = path.indexOf('.') === -1 ? [path] : path.split('.');
|
|
4280
|
+
let cur = obj;
|
|
4281
|
+
for (let i = 0; i < pieces.length - 1; ++i) {
|
|
4282
|
+
cur = cur[pieces[i]];
|
|
4359
4283
|
}
|
|
4360
4284
|
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
}
|
|
4367
|
-
|
|
4285
|
+
const val = get(obj, path, void 0);
|
|
4286
|
+
promises.push(
|
|
4287
|
+
schemaType.doValidate(val, context, { path: path }).catch(err => {
|
|
4288
|
+
error = error || new ValidationError();
|
|
4289
|
+
error.addError(path, err);
|
|
4290
|
+
})
|
|
4291
|
+
);
|
|
4292
|
+
}
|
|
4368
4293
|
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4294
|
+
await Promise.all(promises);
|
|
4295
|
+
if (error != null) {
|
|
4296
|
+
throw error;
|
|
4297
|
+
}
|
|
4298
|
+
|
|
4299
|
+
return obj;
|
|
4375
4300
|
};
|
|
4376
4301
|
|
|
4377
4302
|
/**
|
|
@@ -4414,20 +4339,20 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4414
4339
|
* users[0].dog.breed; // undefined because of `select`
|
|
4415
4340
|
*
|
|
4416
4341
|
* @param {Document|Array} docs Either a single document or array of documents to populate.
|
|
4417
|
-
* @param {
|
|
4342
|
+
* @param {object|string} options Either the paths to populate or an object specifying all parameters
|
|
4418
4343
|
* @param {string} [options.path=null] The path to populate.
|
|
4419
4344
|
* @param {string|PopulateOptions} [options.populate=null] Recursively populate paths in the populated documents. See [deep populate docs](https://mongoosejs.com/docs/populate.html#deep-populate).
|
|
4420
4345
|
* @param {boolean} [options.retainNullValues=false] By default, Mongoose removes null and undefined values from populated arrays. Use this option to make `populate()` retain `null` and `undefined` array entries.
|
|
4421
4346
|
* @param {boolean} [options.getters=false] If true, Mongoose will call any getters defined on the `localField`. By default, Mongoose gets the raw value of `localField`. For example, you would need to set this option to `true` if you wanted to [add a `lowercase` getter to your `localField`](https://mongoosejs.com/docs/schematypes.html#schematype-options).
|
|
4422
4347
|
* @param {boolean} [options.clone=false] When you do `BlogPost.find().populate('author')`, blog posts with the same author will share 1 copy of an `author` doc. Enable this option to make Mongoose clone populated docs before assigning them.
|
|
4423
|
-
* @param {
|
|
4424
|
-
* @param {
|
|
4425
|
-
* @param {
|
|
4426
|
-
* @param {
|
|
4427
|
-
* @param {
|
|
4348
|
+
* @param {object|Function} [options.match=null] Add an additional filter to the populate query. Can be a filter object containing [MongoDB query syntax](https://www.mongodb.com/docs/manual/tutorial/query-documents/), or a function that returns a filter object.
|
|
4349
|
+
* @param {boolean} [options.skipInvalidIds=false] By default, Mongoose throws a cast error if `localField` and `foreignField` schemas don't line up. If you enable this option, Mongoose will instead filter out any `localField` properties that cannot be casted to `foreignField`'s schema type.
|
|
4350
|
+
* @param {number} [options.perDocumentLimit=null] For legacy reasons, `limit` with `populate()` may give incorrect results because it only executes a single query for every document being populated. If you set `perDocumentLimit`, Mongoose will ensure correct `limit` per document by executing a separate query for each document to `populate()`. For example, `.find().populate({ path: 'test', perDocumentLimit: 2 })` will execute 2 additional queries if `.find()` returns 2 documents.
|
|
4351
|
+
* @param {boolean} [options.strictPopulate=true] Set to false to allow populating paths that aren't defined in the given model's schema.
|
|
4352
|
+
* @param {object} [options.options=null] Additional options like `limit` and `lean`.
|
|
4428
4353
|
* @param {Function} [options.transform=null] Function that Mongoose will call on every populated document that allows you to transform the populated document.
|
|
4429
|
-
* @param {
|
|
4430
|
-
* @param {
|
|
4354
|
+
* @param {boolean} [options.forceRepopulate=true] Set to `false` to prevent Mongoose from repopulating paths that are already populated
|
|
4355
|
+
* @param {boolean} [options.ordered=false] Set to `true` to execute any populate queries one at a time, as opposed to in parallel. Set this option to `true` if populating multiple paths or paths with multiple models in transactions.
|
|
4431
4356
|
* @return {Promise}
|
|
4432
4357
|
* @api public
|
|
4433
4358
|
*/
|
|
@@ -4472,7 +4397,7 @@ const excludeIdRegGlobal = /\s?-_id\s?/g;
|
|
|
4472
4397
|
|
|
4473
4398
|
async function _populatePath(model, docs, populateOptions) {
|
|
4474
4399
|
if (populateOptions.strictPopulate == null) {
|
|
4475
|
-
if (populateOptions._localModel
|
|
4400
|
+
if (populateOptions._localModel?.schema._userProvidedOptions.strictPopulate != null) {
|
|
4476
4401
|
populateOptions.strictPopulate = populateOptions._localModel.schema._userProvidedOptions.strictPopulate;
|
|
4477
4402
|
} else if (populateOptions._localModel != null && model.base.options.strictPopulate != null) {
|
|
4478
4403
|
populateOptions.strictPopulate = model.base.options.strictPopulate;
|
|
@@ -4556,7 +4481,7 @@ async function _populatePath(model, docs, populateOptions) {
|
|
|
4556
4481
|
}
|
|
4557
4482
|
}
|
|
4558
4483
|
|
|
4559
|
-
if (mod.options.options
|
|
4484
|
+
if (mod.options.options?.limit != null) {
|
|
4560
4485
|
assignmentOpts.originalLimit = mod.options.options.limit;
|
|
4561
4486
|
} else if (mod.options.limit != null) {
|
|
4562
4487
|
assignmentOpts.originalLimit = mod.options.limit;
|
|
@@ -4579,20 +4504,35 @@ async function _populatePath(model, docs, populateOptions) {
|
|
|
4579
4504
|
return;
|
|
4580
4505
|
}
|
|
4581
4506
|
|
|
4507
|
+
// Track deferred populates per-param (per model) to avoid mixing them
|
|
4508
|
+
const deferredPopulatesPerParam = new Map();
|
|
4509
|
+
|
|
4582
4510
|
if (populateOptions.ordered) {
|
|
4583
4511
|
// Populate in series, primarily for transactions because MongoDB doesn't support multiple operations on
|
|
4584
4512
|
// one transaction in parallel.
|
|
4585
|
-
for (
|
|
4586
|
-
|
|
4513
|
+
for (let i = 0; i < params.length; i++) {
|
|
4514
|
+
const arr = params[i];
|
|
4515
|
+
const { docs, deferredPopulates } = await _execPopulateQuery.apply(null, arr);
|
|
4516
|
+
vals = vals.concat(docs);
|
|
4517
|
+
if (deferredPopulates.length > 0) {
|
|
4518
|
+
deferredPopulatesPerParam.set(i, deferredPopulates);
|
|
4519
|
+
}
|
|
4587
4520
|
}
|
|
4588
4521
|
} else {
|
|
4589
4522
|
// By default, populate in parallel
|
|
4590
4523
|
const promises = [];
|
|
4591
4524
|
for (const arr of params) {
|
|
4592
|
-
promises.push(_execPopulateQuery.apply(null, arr)
|
|
4525
|
+
promises.push(_execPopulateQuery.apply(null, arr));
|
|
4593
4526
|
}
|
|
4594
4527
|
|
|
4595
|
-
await Promise.all(promises);
|
|
4528
|
+
const results = await Promise.all(promises);
|
|
4529
|
+
for (let i = 0; i < results.length; i++) {
|
|
4530
|
+
const { docs, deferredPopulates } = results[i];
|
|
4531
|
+
vals = vals.concat(docs);
|
|
4532
|
+
if (deferredPopulates.length > 0) {
|
|
4533
|
+
deferredPopulatesPerParam.set(i, deferredPopulates);
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4596
4536
|
}
|
|
4597
4537
|
|
|
4598
4538
|
|
|
@@ -4605,12 +4545,49 @@ async function _populatePath(model, docs, populateOptions) {
|
|
|
4605
4545
|
_assign(model, vals, mod, assignmentOpts);
|
|
4606
4546
|
}
|
|
4607
4547
|
|
|
4548
|
+
// Handle deferred populate for cases with per-document match functions.
|
|
4549
|
+
// We defer populate so sift filtering can compare ObjectIds (not populated docs).
|
|
4550
|
+
// This handles both explicit sub-populate and populate added by pre('find') hooks.
|
|
4551
|
+
// Each param's deferred populates are tracked separately to avoid mixing them
|
|
4552
|
+
// between different models (e.g., when using refPath with multiple model types).
|
|
4553
|
+
if (deferredPopulatesPerParam.size > 0) {
|
|
4554
|
+
for (let i = 0; i < params.length; i++) {
|
|
4555
|
+
const arr = params[i];
|
|
4556
|
+
const mod = arr[0];
|
|
4557
|
+
if (!Array.isArray(mod.match)) {
|
|
4558
|
+
continue;
|
|
4559
|
+
}
|
|
4560
|
+
|
|
4561
|
+
const paramDeferredPopulates = deferredPopulatesPerParam.get(i);
|
|
4562
|
+
if (!paramDeferredPopulates || paramDeferredPopulates.length === 0) {
|
|
4563
|
+
continue;
|
|
4564
|
+
}
|
|
4565
|
+
|
|
4566
|
+
// Get the assigned (filtered) children from parent docs
|
|
4567
|
+
const childDocsToPopulate = [];
|
|
4568
|
+
for (const doc of mod.docs) {
|
|
4569
|
+
const childVal = doc.$__ != null ? doc.get(mod.options.path) : doc[mod.options.path];
|
|
4570
|
+
if (Array.isArray(childVal)) {
|
|
4571
|
+
childDocsToPopulate.push(...childVal);
|
|
4572
|
+
} else if (childVal != null) {
|
|
4573
|
+
childDocsToPopulate.push(childVal);
|
|
4574
|
+
}
|
|
4575
|
+
}
|
|
4576
|
+
|
|
4577
|
+
if (childDocsToPopulate.length > 0) {
|
|
4578
|
+
for (const pop of paramDeferredPopulates) {
|
|
4579
|
+
await mod.model.populate(childDocsToPopulate, pop);
|
|
4580
|
+
}
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4608
4585
|
for (const arr of params) {
|
|
4609
4586
|
removeDeselectedForeignField(arr[0].foreignField, arr[0].options, vals);
|
|
4610
4587
|
}
|
|
4611
4588
|
for (const arr of params) {
|
|
4612
4589
|
const mod = arr[0];
|
|
4613
|
-
if (mod.options
|
|
4590
|
+
if (mod.options?.options?._leanTransform) {
|
|
4614
4591
|
for (const doc of vals) {
|
|
4615
4592
|
mod.options.options._leanTransform(doc);
|
|
4616
4593
|
}
|
|
@@ -4647,6 +4624,12 @@ function _execPopulateQuery(mod, match, select) {
|
|
|
4647
4624
|
queryOptions.limit = queryOptions.limit * mod.ids.length;
|
|
4648
4625
|
}
|
|
4649
4626
|
|
|
4627
|
+
// When there's a per-document match function, defer any populate (including from hooks)
|
|
4628
|
+
// until after sift filtering, otherwise sift compares ObjectIds against populated docs.
|
|
4629
|
+
if (Array.isArray(mod.match)) {
|
|
4630
|
+
queryOptions._deferPopulate = true;
|
|
4631
|
+
}
|
|
4632
|
+
|
|
4650
4633
|
const query = mod.model.find(match, select, queryOptions);
|
|
4651
4634
|
// If we're doing virtual populate and projection is inclusive and foreign
|
|
4652
4635
|
// field is not selected, automatically select it because mongoose needs it.
|
|
@@ -4668,7 +4651,14 @@ function _execPopulateQuery(mod, match, select) {
|
|
|
4668
4651
|
}
|
|
4669
4652
|
}
|
|
4670
4653
|
|
|
4671
|
-
// If we need to sub-populate, call populate recursively
|
|
4654
|
+
// If we need to sub-populate, call populate recursively.
|
|
4655
|
+
// However, if we have a per-document match function (Array.isArray(mod.match)),
|
|
4656
|
+
// defer sub-populate until after sift filtering, otherwise sift compares
|
|
4657
|
+
// ObjectIds against already-populated docs and fails to match.
|
|
4658
|
+
const shouldDeferSubPopulate = subPopulate && Array.isArray(mod.match);
|
|
4659
|
+
|
|
4660
|
+
// Prepare sub-populate options with necessary metadata (_fullPath, strictPopulate, _localModel).
|
|
4661
|
+
// This must be done for both immediate and deferred sub-populate cases.
|
|
4672
4662
|
if (subPopulate) {
|
|
4673
4663
|
// If subpopulating on a discriminator, skip check for non-existent
|
|
4674
4664
|
// paths. Because the discriminator may not have the path defined.
|
|
@@ -4686,11 +4676,21 @@ function _execPopulateQuery(mod, match, select) {
|
|
|
4686
4676
|
if (Array.isArray(subPopulate)) {
|
|
4687
4677
|
for (const pop of subPopulate) {
|
|
4688
4678
|
pop._fullPath = basePath + '.' + pop.path;
|
|
4679
|
+
// Set _localModel for deferred populates so strictPopulate works correctly
|
|
4680
|
+
if (shouldDeferSubPopulate && pop._localModel == null) {
|
|
4681
|
+
pop._localModel = mod.model;
|
|
4682
|
+
}
|
|
4689
4683
|
}
|
|
4690
4684
|
} else if (typeof subPopulate === 'object') {
|
|
4691
4685
|
subPopulate._fullPath = basePath + '.' + subPopulate.path;
|
|
4686
|
+
// Set _localModel for deferred populates so strictPopulate works correctly
|
|
4687
|
+
if (shouldDeferSubPopulate && subPopulate._localModel == null) {
|
|
4688
|
+
subPopulate._localModel = mod.model;
|
|
4689
|
+
}
|
|
4692
4690
|
}
|
|
4691
|
+
}
|
|
4693
4692
|
|
|
4693
|
+
if (subPopulate && !shouldDeferSubPopulate) {
|
|
4694
4694
|
query.populate(subPopulate);
|
|
4695
4695
|
}
|
|
4696
4696
|
|
|
@@ -4699,7 +4699,16 @@ function _execPopulateQuery(mod, match, select) {
|
|
|
4699
4699
|
for (const val of docs) {
|
|
4700
4700
|
leanPopulateMap.set(val, mod.model);
|
|
4701
4701
|
}
|
|
4702
|
-
|
|
4702
|
+
// Return both docs and any deferred populates (from hooks or explicit sub-populate)
|
|
4703
|
+
const deferredPopulates = [];
|
|
4704
|
+
if (query._deferredPopulate) {
|
|
4705
|
+
deferredPopulates.push(...query._deferredPopulate);
|
|
4706
|
+
delete query._deferredPopulate;
|
|
4707
|
+
}
|
|
4708
|
+
if (shouldDeferSubPopulate) {
|
|
4709
|
+
deferredPopulates.push(subPopulate);
|
|
4710
|
+
}
|
|
4711
|
+
return { docs, deferredPopulates };
|
|
4703
4712
|
}
|
|
4704
4713
|
);
|
|
4705
4714
|
}
|
|
@@ -4741,14 +4750,7 @@ function _assign(model, vals, mod, assignmentOpts) {
|
|
|
4741
4750
|
if (__val instanceof Document) {
|
|
4742
4751
|
__val = __val._doc._id;
|
|
4743
4752
|
}
|
|
4744
|
-
|
|
4745
|
-
// Workaround for gh-15315 because Mongoose UUIDs don't use BSON UUIDs yet.
|
|
4746
|
-
key = String(__val.toUUID());
|
|
4747
|
-
} else if (__val?.constructor?.name === 'Buffer' && __val._subtype === 4 && typeof __val.toUUID === 'function') {
|
|
4748
|
-
key = String(__val.toUUID());
|
|
4749
|
-
} else {
|
|
4750
|
-
key = String(__val);
|
|
4751
|
-
}
|
|
4753
|
+
key = String(__val);
|
|
4752
4754
|
if (rawDocs[key]) {
|
|
4753
4755
|
if (Array.isArray(rawDocs[key])) {
|
|
4754
4756
|
rawDocs[key].push(val);
|
|
@@ -4771,14 +4773,7 @@ function _assign(model, vals, mod, assignmentOpts) {
|
|
|
4771
4773
|
if (_val instanceof Document) {
|
|
4772
4774
|
_val = _val._doc._id;
|
|
4773
4775
|
}
|
|
4774
|
-
|
|
4775
|
-
// Workaround for gh-15315 because Mongoose UUIDs don't use BSON UUIDs yet.
|
|
4776
|
-
key = String(_val.toUUID());
|
|
4777
|
-
} else if (_val?.constructor?.name === 'Buffer' && _val._subtype === 4 && typeof _val.toUUID === 'function') {
|
|
4778
|
-
key = String(_val.toUUID());
|
|
4779
|
-
} else {
|
|
4780
|
-
key = String(_val);
|
|
4781
|
-
}
|
|
4776
|
+
key = String(_val);
|
|
4782
4777
|
if (rawDocs[key]) {
|
|
4783
4778
|
if (Array.isArray(rawDocs[key])) {
|
|
4784
4779
|
rawDocs[key].push(val);
|
|
@@ -4830,9 +4825,9 @@ function _assign(model, vals, mod, assignmentOpts) {
|
|
|
4830
4825
|
/**
|
|
4831
4826
|
* Compiler utility.
|
|
4832
4827
|
*
|
|
4833
|
-
* @param {
|
|
4828
|
+
* @param {string|Function} name model name or class extending Model
|
|
4834
4829
|
* @param {Schema} schema
|
|
4835
|
-
* @param {
|
|
4830
|
+
* @param {string} collectionName
|
|
4836
4831
|
* @param {Connection} connection
|
|
4837
4832
|
* @param {Mongoose} base mongoose instance
|
|
4838
4833
|
* @api private
|
|
@@ -4899,7 +4894,6 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
|
|
|
4899
4894
|
model.events = new EventEmitter();
|
|
4900
4895
|
|
|
4901
4896
|
schema._preCompile();
|
|
4902
|
-
|
|
4903
4897
|
const _userProvidedOptions = schema._userProvidedOptions || {};
|
|
4904
4898
|
|
|
4905
4899
|
const collectionOptions = {
|
|
@@ -4955,7 +4949,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
|
|
|
4955
4949
|
Model.clientEncryption = function clientEncryption() {
|
|
4956
4950
|
const ClientEncryption = this.base.driver.get().ClientEncryption;
|
|
4957
4951
|
if (!ClientEncryption) {
|
|
4958
|
-
throw new
|
|
4952
|
+
throw new MongooseError('The mongodb driver must be used to obtain a ClientEncryption object.');
|
|
4959
4953
|
}
|
|
4960
4954
|
|
|
4961
4955
|
const client = this.collection?.conn?.client;
|
|
@@ -5026,7 +5020,7 @@ function applyQueryMethods(model, methods) {
|
|
|
5026
5020
|
*
|
|
5027
5021
|
* @param {Connection} conn
|
|
5028
5022
|
* @param {Schema} [schema]
|
|
5029
|
-
* @param {
|
|
5023
|
+
* @param {string} [collection]
|
|
5030
5024
|
* @return {Model}
|
|
5031
5025
|
* @api private
|
|
5032
5026
|
* @memberOf Model
|
|
@@ -5179,7 +5173,7 @@ Model._applyQueryMiddleware = function _applyQueryMiddleware() {
|
|
|
5179
5173
|
return !!contexts.query;
|
|
5180
5174
|
}
|
|
5181
5175
|
if (hook.name === 'deleteOne' || hook.name === 'updateOne') {
|
|
5182
|
-
return !!contexts.query ||
|
|
5176
|
+
return !!contexts.query || utils.hasOwnKeys(contexts) === false;
|
|
5183
5177
|
}
|
|
5184
5178
|
if (hook.query != null || hook.document != null) {
|
|
5185
5179
|
return !!hook.query;
|