CRUD API
- Status: Accepted
- Minimum Server Version: 2.6
Abstract
The CRUD API defines a set of related methods and structures defining a driver's API. As not all languages/frameworks have the same abilities, parts of the spec may or may not apply. These sections have been called out.
Specification
This specification is about Guidance in 3 areas related to the CRUD API as well as a specification for the API itself. It does not define implementation details and provides room and flexibility for the idioms and differences in languages and frameworks.
Definitions
META
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Terms
Collection:
The term interface Collection
will be seen in most of the sections. Each driver will likely have a class or interface
defined for the concept of a collection. Operations appearing inside the interface Collection
are required operations
to be present on a driver's concept of a collection.
Iterable:
The term Iterable
will be seen as a return type from some of the Read methods. Its use is as that of a
sequence of items. For instance, collection.find({})
returns a sequence of documents that can be iterated over.
Guidance
Documentation
The documentation provided in code below is merely for driver authors and SHOULD NOT be taken as required documentation for the driver.
Operations
All drivers MUST offer the operations defined in the following sections. This does not preclude a driver from offering more.
Operation Parameters
All drivers MUST offer the same options for each operation as defined in the following sections. This does not preclude
a driver from offering more. A driver SHOULD NOT require a user to specify optional parameters, denoted by the
Optional<>
signature. Unless otherwise specified, optional values should not be sent to the server.
Deviations
A non-exhaustive list of acceptable deviations are as follows:
-
Using named parameters instead of an options hash. For instance,
collection.find({x:1}, sort: {a: -1})
. -
When using an
Options
class, if multipleOptions
classes are structurally equatable, it is permissible to consolidate them into one with a clear name. For instance, it would be permissible to use the nameUpdateOptions
as the options forUpdateOne
andUpdateMany
. -
Using a fluent style builder for find or aggregate:
collection.find({x: 1}).sort({a: -1}).skip(10);
When using a fluent-style builder, all options should be named rather than inventing a new word to include in the pipeline (like options). Required parameters are still required to be on the initiating method.
In addition, it is imperative that documentation indicate when the order of operations is important. For instance, skip and limit in find is order irrelevant where skip and limit in aggregate is not.
Naming
All drivers MUST name operations, objects, and parameters as defined in the following sections.
Deviations are permitted as outlined below.
Deviations
When deviating from a defined name, an author should consider if the altered name is recognizable and discoverable to the user of another driver.
A non-exhaustive list of acceptable naming deviations are as follows:
- Using "batchSize" as an example, Java would use "batchSize" while Python would use "batch_size". However, calling it "batchCount" would not be acceptable.
- Using "maxTimeMS" as an example, .NET would use "MaxTime" where it's type is a TimeSpan structure that includes units. However, calling it "MaximumTime" would not be acceptable.
- Using "FindOptions" as an example, Javascript wouldn't need to name it while other drivers might prefer to call it "FindArgs" or "FindParams". However, calling it "QueryOptions" would not be acceptable.
- Using "isOrdered" rather than "ordered". Some languages idioms prefer the use of "is", "has", or "was" and this is acceptable.
Timeouts
Drivers MUST enforce timeouts for all operations per the Client Side Operations Timeout specification. All operations that return cursors MUST support the timeout options documented in the Cursors section of that specification. All explain helpers MUST support the timeout options documented in the Explain Helpers section of that specification.
API
Read
[!NOTE] The term
Iterable<T>
is used below to indicate many of T. This spec is flexible on what that means as different drivers will have different requirements, types, and idioms.
interface Collection {
/**
* Runs an aggregation framework pipeline.
*
* Note: $out and $merge are special pipeline stages that cause no results
* to be returned from the server. As such, the iterable here would never
* contain documents. Drivers MAY setup a cursor to be executed upon
* iteration against the output collection such that if a user were to
* iterate the return value, results would be returned.
*
* Note: result iteration should be backed by a cursor. Depending on the implementation,
* the cursor may back the returned Iterable instance or an iterator that it produces.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
aggregate(pipeline: Document[], options: Optional<AggregateOptions>): Iterable<Document>;
/**
* Gets the number of documents matching the filter.
*
* **This method is DEPRECATED and should not be implemented in new drivers.**
*
* @see https://www.mongodb.com/docs/manual/reference/command/count/
@deprecated 4.0
*/
count(filter: Document, options: Optional<CountOptions>): Int64;
/**
* Count the number of documents in a collection that match the given
* filter. Note that an empty filter will force a scan of the entire
* collection. For a fast count of the total documents in a collection
* see estimatedDocumentCount.
*
* See "Count API Details" section below.
*/
countDocuments(filter: Document, options: Optional<CountOptions>): Int64;
/**
* Gets an estimate of the count of documents in a collection using collection metadata.
*
* See "Count API Details" section below for implementation and documentation
* requirements.
*/
estimatedDocumentCount(options: Optional<EstimatedDocumentCountOptions>): Int64;
/**
* Finds the distinct values for a specified field across a single collection.
*
* Note: the results are backed by the "values" array in the distinct command's result
* document. This differs from aggregate and find, where results are backed by a cursor.
*
* @see https://www.mongodb.com/docs/manual/reference/command/distinct/
*/
distinct(fieldName: string, filter: Document, options: Optional<DistinctOptions>): Iterable<any>;
/**
* Finds the documents matching the model.
*
* Note: result iteration should be backed by a cursor. Depending on the implementation,
* the cursor may back the returned Iterable instance or an iterator that it produces.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
find(filter: Document, options: Optional<FindOptions>): Iterable<Document>;
/**
* Find a document matching the model.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
findOne(filter: Document, options: Optional<FindOneOptions>): Optional<Document>;
}
interface Database {
/**
* Runs an aggregation framework pipeline on the database for pipeline stages
* that do not require an underlying collection, such as $currentOp and $listLocalSessions.
*
* Note: result iteration should be backed by a cursor. Depending on the implementation,
* the cursor may back the returned Iterable instance or an iterator that it produces.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/#dbcmd.aggregate
*/
aggregate(pipeline: Document[], options: Optional<AggregateOptions>): Iterable<Document>;
}
class AggregateOptions {
/**
* Enables writing to temporary files. When set to true, aggregation stages
* can write data to the _tmp subdirectory in the dbPath directory.
*
* This option is sent only if the caller explicitly provides a value. The default
* is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
allowDiskUse: Optional<Boolean>;
/**
* The number of documents to return per batch.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* If specified, drivers SHOULD apply this option to both the original aggregate command and subsequent
* getMore operations on the cursor.
*
* Drivers MUST NOT specify a batchSize of zero in an aggregate command that includes an $out or $merge stage,
* as that will prevent the pipeline from executing. Drivers SHOULD leave the cursor.batchSize command option
* unset in an aggregate command that includes an $out or $merge stage.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
batchSize: Optional<Int32>;
/**
* If true, allows the write to opt-out of document level validation. This only applies
* when the $out or $merge stage is specified.
*
* This option is sent only if the caller explicitly provides a true value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
collation: Optional<Document>;
/**
* The maximum amount of time to allow the query to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
maxTimeMS: Optional<Int64>;
/**
* The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor
* query.
*
* This options only applies to aggregations which return a TAILABLE_AWAIT cursor. Drivers
* SHOULD always send this value, if the cursor is not a TAILABLE_AWAIT cursor the server will
* ignore it.
*
* @note this option is an alias for maxTimeMS, used on getMore commands
* @note this option is not set on the aggregate command
*/
maxAwaitTimeMS: Optional<Int64>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions between 3.6 and 4.2 only support string as comment,
* and providing a non-string type will result in a server-side error.
* Older server versions do not support comment for aggregate command at all,
* and providing one will result in a server-side error.
*
* If a comment is provided, drivers MUST attach this comment to all
* subsequent getMore commands run on the same cursor for server
* versions 4.4 and above. For server versions below 4.4 drivers MUST NOT
* attach a comment to getMore commands.
*/
comment: Optional<any>;
/**
* The index to use for the aggregation. The hint does not apply to $lookup and $graphLookup stages.
* Specify either the index name as a string or the index key pattern. If specified,
* then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
hint: Optional<(String | Document)>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate/
*/
let: Optional<Document>;
}
class CountOptions {
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*/
hint: Optional<(String | Document)>;
/**
* The maximum number of documents to count.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*/
limit: Optional<Int64>;
/**
* The maximum amount of time to allow the operation to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*/
maxTimeMS: Optional<Int64>;
/**
* The number of documents to skip before counting.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*/
skip: Optional<Int64>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for count command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
}
class EstimatedDocumentCountOptions {
/**
* The maximum amount of time to allow the operation to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*/
maxTimeMS: Optional<Int64>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4.14 and above.
* For server versions between 4.4.0 and 4.4.14 string comment is supported.
* Servers versions below 4.4.0 do not support comment for count command,
* which is used to implement estimatedDocumentCount. Therefore, providing a
* comment may result in a server-side error.
*/
comment: Optional<any>;
}
class DistinctOptions {
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/distinct/
*/
collation: Optional<Document>;
/**
* The maximum amount of time to allow the query to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*
* @see https://www.mongodb.com/docs/manual/reference/command/distinct/
*/
maxTimeMS: Optional<Int64>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for distinct command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
hint: Optional<(String | Document)>;
}
enum CursorType {
/**
* The default value. A vast majority of cursors will be of this type.
*/
NON_TAILABLE,
/**
* Tailable means the cursor is not closed when the last data is retrieved.
* Rather, the cursor marks the final object’s position. You can resume
* using the cursor later, from where it was located, if more data were
* received. Like any "latent cursor", the cursor may become invalid at
* some point (CursorNotFound) – for example if the final object it
* references were deleted.
*
* @see https://www.mongodb.com/docs/meta-driver/latest/legacy/mongodb-wire-protocol/#op-query
*/
TAILABLE,
/**
* Combines the tailable option with awaitData, as defined below.
*
* Use with TailableCursor. If we are at the end of the data, block for a
* while rather than returning no data. After a timeout period, we do return
* as normal. The default is true.
*
* @see https://www.mongodb.com/docs/meta-driver/latest/legacy/mongodb-wire-protocol/#op-query
*/
TAILABLE_AWAIT
}
class FindOptions {
/**
* Enables writing to temporary files on the server. When set to true, the server
* can write temporary data to disk while executing the find operation.
*
* This option is sent only if the caller explicitly provides a value. The default
* is to not send a value.
*
* This option is only supported by servers >= 4.4. Older servers >= 3.2 will report an error for using this option.
* For servers < 3.2, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
allowDiskUse: Optional<Boolean>;
/**
* Get partial results from a mongos if some shards are down (instead of throwing an error).
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, the Partial wire protocol flag is used and defaults to false.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
allowPartialResults: Optional<Boolean>;
/**
* The number of documents to return per batch.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this is combined with limit to create the wire protocol numberToReturn value.
* If specified, drivers SHOULD apply this option to both the original query operation and subsequent
* getMore operations on the cursor.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
batchSize: Optional<Int32>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
collation: Optional<Document>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 only support string as comment,
* and providing a non-string type will result in a server-side error.
*
* If a comment is provided, drivers MUST attach this comment to all
* subsequent getMore commands run on the same cursor for server
* versions 4.4 and above. For server versions below 4.4 drivers MUST NOT
* attach a comment to getMore commands.
*/
comment: Optional<any>;
/**
* Indicates the type of cursor to use. This value includes both
* the tailable and awaitData options.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, the AwaitData and Tailable wire protocol flags are used and default to false.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
cursorType: Optional<CursorType>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
hint: Optional<(String | Document)>;
/**
* The maximum number of documents to return.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this is combined with batchSize to create the wire protocol numberToReturn value.
*
* A negative limit implies that the caller has requested a single batch of results. For servers >= 3.2, singleBatch
* should be set to true and limit should be converted to a positive value. For servers < 3.2, the wire protocol
* numberToReturn value may be negative.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
limit: Optional<Int64>;
/**
* The exclusive upper bound for a specific index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
max: Optional<Document>;
/**
* The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor
* query. This only applies to a TAILABLE_AWAIT cursor. When the cursor is not a TAILABLE_AWAIT cursor,
* this option is ignored.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as maxTimeMS does not exist in the OP_GET_MORE wire protocol.
*
* Note: This option is specified as "maxTimeMS" in the getMore command and not provided as part of the
* initial find command.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
maxAwaitTimeMS: Optional<Int64>;
/**
* Maximum number of documents or index keys to scan when executing the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
* @deprecated 4.0
*/
maxScan: Optional<Int64>;
/**
* The maximum amount of time to allow the query to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
maxTimeMS: Optional<Int64>;
/**
* The inclusive lower bound for a specific index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
min: Optional<Document>;
/**
* The server normally times out idle cursors after an inactivity period (10 minutes)
* to prevent excess memory use. Set this option to prevent that.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, the NoCursorTimeout wire protocol flag is used and defaults to false.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
noCursorTimeout: Optional<Boolean>;
/**
* Enables optimization when querying the oplog for a range of ts values
*
* Note: this option is intended for internal replication use only.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, the OplogReplay wire protocol flag is used and defaults to false.
* For servers >= 4.4, the server will ignore this option if set (see: SERVER-36186).
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
* @deprecated 4.4
*/
oplogReplay: Optional<Boolean>;
/**
* Limits the fields to return for all matching documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
projection: Optional<Document>;
/**
* If true, returns only the index keys in the resulting documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
returnKey: Optional<Boolean>;
/**
* Determines whether to return the record identifier for each document. If true, adds a field $recordId to the returned documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
showRecordId: Optional<Boolean>;
/**
* The number of documents to skip before returning.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this is a wire protocol parameter that defaults to 0.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
skip: Optional<Int64>;
/**
* Prevents the cursor from returning a document more than once because of an intervening write operation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
* @deprecated 4.0
*/
snapshot: Optional<Boolean>;
/**
* The order in which to return matching documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
sort: Optional<Document>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/find/
*/
let: Optional<Document>;
}
type FindOneOptions = Omit<FindOptions, 'batchSize' | 'cursorType' | 'limit' | 'noCursorTimeout'>;
Count API Details
MongoDB drivers provide two helpers for counting the number of documents in a collection, estimatedDocumentCount and countDocuments. The names were chosen to make it clear how they behave and exactly what they do. The estimatedDocumentCount helper returns an estimate of the count of documents in the collection using collection metadata, rather than counting the documents or consulting an index. The countDocuments helper counts the documents that match the provided query filter using an aggregation pipeline.
The count() helper is deprecated. It has always been implemented using the count
command. The behavior of the count
command differs depending on the options passed to it and may or may not provide an accurate count. When no query filter
is provided the count command provides an estimate using collection metadata. Even when provided with a query filter the
count command can return inaccurate results with a sharded cluster
if orphaned documents exist or if a chunk migration is in progress.
The countDocuments helper avoids these sharded cluster problems entirely when used with MongoDB 3.6+, and when using
Primary
read preference with older sharded clusters.
estimatedDocumentCount
The estimatedDocumentCount function is implemented using the count
command with no query filter, skip, limit, or other
options that would alter the results. The only supported options are listed in the EstimatedDocumentCountOptions
type
defined above.
Drivers MUST document that, due to an oversight in versions 5.0.0-5.0.8 of MongoDB, the count
command, which
estimatedDocumentCount uses in its implementation, was not included in v1 of the Stable API, and so users of the Stable
API with estimatedDocumentCount are recommended to upgrade their server version to 5.0.9+ or set apiStrict: false
to
avoid encountering errors.
Drivers MUST document that the count
server command is used to implement estimatedDocumentCount and that users can
find more information via Count: Behavior.
The 5.0-compat versions of many drivers updated their estimatedDocumentCount implementations to use the $collStats
aggregation stage instead of the count
command. This had the unintended consequence of breaking estimatedDocumentCount
on views, and so the change was seen as a backwards-incompatible regression and reverted. The release notes for the
driver versions that include the reversion from $collStats
back to count
MUST document the following:
- The 5.0-compat release accidentally broke estimatedDocumentCount on views by changing its implementation to use
aggregate
and a$collStats
stage instead of thecount
command. - The new release is fixing estimatedDocumentCount on views by reverting back to using
count
in its implementation. - Due to an oversight, the
count
command was omitted from the Stable API in server versions 5.0.0 - 5.0.8 and 5.1.0 - 5.3.1, so users of the Stable API with estimatedDocumentCount are recommended to upgrade their MongoDB clusters to 5.0.9 or 5.3.2 (if on Atlas) or setapiStrict: false
when constructing their MongoClients.
countDocuments
The countDocuments function is implemented using the $group
aggregate pipeline stage with $sum
. Applications must be
required to pass a value for filter, but an empty document is supported:
pipeline = [{'$match': filter}]
if (skip) {
pipeline.push({'$skip': skip})
}
if (limit) {
pipeline.push({'$limit': limit})
}
pipeline.push({'$group': {'_id': 1, 'n': {'$sum': 1}}})
Due to countDocuments using the $match
aggregation pipeline stage, certain query operators cannot be used in
countDocuments. This includes the $where
and $near
query operators, among others. Drivers MUST document these
restrictions in their
documentation.
The count of documents is returned in the n
field, similar to the count
command. countDocuments options other than
filter, skip, and limit are added as options to the aggregate
command.
In the event this aggregation is run against an empty collection, an empty array will be returned with no n
field.
Drivers MUST interpret this result as a 0
count.
findOne API details
The findOne
operation is implemented using a find
operation, but only returns the first document returned in the
cursor. Due to the special case, findOne
does not support the following options supported in find
:
batchSize
: drivers MUST NOT set abatchSize
in thefind
command created for afindOne
operationcursorType
:findOne
only supports non-tailable cursorslimit
: drivers MUST setlimit
to 1 in thefind
command created for afindOne
operationnoCursorTimeout
: with alimit
of 1 and nobatchSize
, there will not be an open cursor on the server
To ensure that the cursor is closed regardless of the default server batchSize
, drivers MUST also set
singleBatch: true
in the find
command.
Setting limit and batchSize options for find commands
When users specify both limit
and batchSize
options with the same value, the server returns all results in the first
batch, but still leaves an open cursor that needs to be closed using the killCursors
command. To avoid this, drivers
MUST send a value of limit + 1
for batchSize
in the resulting find
command. This eliminates the open cursor issue.
Combining Limit and Batch Size for OP_QUERY
The OP_QUERY wire protocol only contains a numberToReturn value which drivers must calculate to get expected limit and batch size behavior. Subsequent calls to OP_GET_MORE should use the user-specified batchSize or default to 0. If the result is larger than the max Int32 value, an error MUST be raised as the computed value is impossible to send to the server. Below is pseudo-code for calculating numberToReturn for OP_QUERY.
function calculateFirstNumberToReturn(options: FindOptions): Int32 {
Int32 numberToReturn;
Int32 limit = options.limit || 0;
Int32 batchSize = options.batchSize || 0;
if (limit < 0) {
numberToReturn = limit;
}
else if (limit == 0) {
numberToReturn = batchSize;
}
else if (batchSize == 0) {
numberToReturn = limit;
}
else if (limit < batchSize) {
numberToReturn = limit;
}
else {
numberToReturn = batchSize;
}
return numberToReturn;
}
Because of this anomaly in the wire protocol, it is up to the driver to enforce the user-specified limit. Each driver MUST keep track of how many documents have been iterated and stop iterating once the limit has been reached. When the limit has been reached, if the cursor is still open, a driver MUST kill the cursor.
Database-level aggregation
The server supports several collection-less aggregation source stages like $currentOp
and $listLocalSessions
. The
database aggregate command requires a collection name of 1 for collection-less source stages. Drivers support for
database-level aggregation will allow users to receive a cursor from these collection-less aggregation source stages.
Write
Insert, Update, Replace, Delete, and Bulk Writes
Generated identifiers
The insert and bulk insert operations described below MUST generate identifiers for all documents that do not already have them. These identifiers SHOULD be prepended to the document so they are the first field, in order to prevent the server from spending time re-ordering the document. If a document already has a user-provided identifier, the driver MAY re-order the document so the identifier is the first field.
interface Collection {
/**
* Executes multiple write operations.
*
* An error MUST be raised if the requests parameter is empty.
*
* For servers < 3.4, if a collation was explicitly set for any request, an error MUST be raised
* and no documents sent.
*
* NOTE: see the FAQ about the previous bulk API and how it relates to this.
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
* @see https://www.mongodb.com/docs/manual/reference/command/insert/
* @see https://www.mongodb.com/docs/manual/reference/command/update/
* @throws InvalidArgumentException if requests is empty
* @throws BulkWriteException
*/
bulkWrite(requests: WriteModel[], options: Optional<BulkWriteOptions>): Optional<BulkWriteResult>;
/**
* Inserts the provided document. If the document is missing an identifier,
* the driver should generate one.
*
* @see https://www.mongodb.com/docs/manual/reference/command/insert/
* @throws WriteException
*/
insertOne(document: Document, options: Optional<InsertOneOptions>): Optional<InsertOneResult>;
/**
* Inserts the provided documents. If any documents are missing an identifier,
* the driver should generate them.
*
* An error MUST be raised if the documents parameter is empty.
*
* Note that this uses the bulk insert command underneath and should not
* use OP_INSERT.
*
* @see https://www.mongodb.com/docs/manual/reference/command/insert/
* @throws InvalidArgumentException if documents is empty
* @throws BulkWriteException
*/
insertMany(documents: Iterable<Document>, options: Optional<InsertManyOptions>): Optional<InsertManyResult>;
/**
* Deletes one document.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
* @throws WriteException
*/
deleteOne(filter: Document, options: Optional<DeleteOptions>): Optional<DeleteResult>;
/**
* Deletes multiple documents.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
* @throws WriteException
*/
deleteMany(filter: Document, options: Optional<DeleteOptions>): Optional<DeleteResult>;
/**
* Replaces a single document.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
* @throws WriteException
*/
replaceOne(filter: Document, replacement: Document, options: Optional<ReplaceOptions>): Optional<UpdateResult>;
/**
* Updates one document.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
* @throws WriteException
*/
updateOne(filter: Document, update: (Document | Document[]), options: Optional<UpdateOptions>): Optional<UpdateResult>;
/**
* Updates multiple documents.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
* @throws WriteException
*/
updateMany(filter: Document, update: (Document | Document[]), options: Optional<UpdateOptions>): Optional<UpdateResult>;
}
class BulkWriteOptions {
/**
* If true, when a write fails, return without performing the remaining
* writes. If false, when a write fails, continue with the remaining writes, if any.
* Defaults to true.
*/
ordered: Boolean;
/**
* If true, allows the write to opt-out of document level validation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
* For unacknowledged writes using OP_INSERT, OP_UPDATE, or OP_DELETE, the driver MUST raise an error if the caller explicitly provides a value.
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for write operations,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
/**
* Map of parameter names and values. Values must be constant or closed expressions that do not
* reference document fields. Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* The let parameter must be a valid Document type for server versions 5.0 and above.
* Server versions prior to 5.0 do not support the let parameter for bulk write operations,
* and providing it will result in a server-side error.
*
* The value of let will be passed to all update and delete, but not insert, commands.
*/
let: Optional<Document>;
}
class InsertOneOptions {
/**
* If true, allows the write to opt-out of document level validation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
* For unacknowledged writes using OP_INSERT, the driver MUST raise an error if the caller explicitly provides a value.
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for insert command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
}
class InsertManyOptions {
/**
* If true, allows the write to opt-out of document level validation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
* For unacknowledged writes using OP_INSERT, the driver MUST raise an error if the caller explicitly provides a value.
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* If true, when an insert fails, return without performing the remaining
* writes. If false, when a write fails, continue with the remaining writes, if any.
* Defaults to true.
*/
ordered: Boolean;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for insert command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
}
class UpdateOptions {
/**
* A set of filters specifying to which array elements an update should apply.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.6, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
arrayFilters: Optional<Array<Document>>;
/**
* If true, allows the write to opt-out of document level validation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.2. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_MSG and servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
hint: Optional<(String | Document)>;
/**
* When true, creates a new document if no document matches the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
upsert: Optional<Boolean>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
let: Optional<Document>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for update command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
/**
* Specify which document the operation updates if the query matches multiple
* documents. The first document matched by the sort order will be updated.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* The server will report an error if the caller explicitly provides a value with updateMany().
* This option is only supported by servers >= 8.0. Older servers will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
sort: Optional<Document>;
}
class ReplaceOptions {
/**
* If true, allows the write to opt-out of document level validation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.2. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_MSG and servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
hint: Optional<(String | Document)>;
/**
* When true, creates a new document if no document matches the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
upsert: Optional<Boolean>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
let: Optional<Document>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for update command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
/**
* Specify which document the operation replaces if the query matches multiple
* documents. The first document matched by the sort order will be replaced.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 8.0. Older servers will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
sort: Optional<Document>;
}
class DeleteOptions {
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_DELETE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.4. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_DELETE, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_MSG and servers < 4.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
hint: Optional<(String | Document)>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
let: Optional<Document>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for delete command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
}
Bulk Write Models
interface WriteModel {
// marker interface for writes that can be batched together.
}
class InsertOneModel implements WriteModel {
/**
* The document to insert.
*
* @see https://www.mongodb.com/docs/manual/reference/command/insert/
*/
document: Document;
}
class DeleteOneModel implements WriteModel {
/**
* The filter to limit the deleted documents.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
filter: Document;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_DELETE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.4. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_DELETE, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_MSG and servers < 4.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
hint: Optional<(String | Document)>;
}
class DeleteManyModel implements WriteModel {
/**
* The filter to limit the deleted documents.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
filter: Document;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_DELETE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.4. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_DELETE or OP_MSG, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/delete/
*/
hint: Optional<(String | Document)>;
}
class ReplaceOneModel implements WriteModel {
/**
* The filter to limit the replaced document.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
filter: Document;
/**
* The document with which to replace the matched document.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
replacement: Document;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.2. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_MSG and servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
hint: Optional<(String | Document)>;
/**
* Specify which document the operation replaces if the query matches multiple
* documents. The first document matched by the sort order will be replaced.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 8.0. Older servers will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
sort: Optional<Document>;
/**
* When true, creates a new document if no document matches the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
upsert: Optional<Boolean>;
}
class UpdateOneModel implements WriteModel {
/**
* The filter to limit the updated documents.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
filter: Document;
/**
* A document or pipeline containing update operators.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
update: (Document | Document[]);
/**
* A set of filters specifying to which array elements an update should apply.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.6, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
arrayFilters: Optional<Array<Document>>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.2. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_MSG and servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
hint: Optional<(String | Document)>;
/**
* Specify which document the operation updates if the query matches multiple
* documents. The first document matched by the sort order will be updated.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 8.0. Older servers will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
sort: Optional<Document>;
/**
* When true, creates a new document if no document matches the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
upsert: Optional<Boolean>;
}
class UpdateManyModel implements WriteModel {
/**
* The filter to limit the updated documents.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
filter: Document;
/**
* A document or pipeline containing update operators.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
update: (Document | Document[]);
/**
* A set of filters specifying to which array elements an update should apply.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.6, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
arrayFilters: Optional<Array<Document>>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.2. Older servers >= 3.4 will report an error for using this option.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_UPDATE, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes using OP_MSG and servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
hint: Optional<(String | Document)>;
/**
* When true, creates a new document if no document matches the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
upsert: Optional<Boolean>;
}
Write Results
The acknowledged property is defined for languages/frameworks without a sufficient optional type. Hence, a driver may
choose to return an optional result (e.g. Optional<BulkWriteResult>
) such that unacknowledged writes don't have a
value and acknowledged writes do have a value.
[!NOTE] If you have a choice, consider providing the acknowledged member and raising an error if the other fields are accessed in an unacknowledged write. Instead of users receiving a null reference exception, you have the opportunity to provide an informative error message indicating the correct way to handle the situation. For instance, "The insertedCount member is not available when the write was unacknowledged. Check the acknowledged member to avoid this error."
Any result class with all parameters marked NOT REQUIRED is ultimately NOT REQUIRED as well. For instance, the
InsertOneResult
has all NOT REQUIRED parameters and is therefore also NOT REQUIRED allowing a driver to use "void" as
the return value for the insertOne
method.
class BulkWriteResult {
/**
* Indicates whether this write result was acknowledged. If not, then all
* other members of this result will be undefined.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
acknowledged: Boolean;
/**
* Number of documents inserted.
*/
insertedCount: Int64;
/**
* Map of the index of the operation to the id of the inserted document.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
insertedIds: Map<Int64, any>;
/**
* Number of documents matched for update.
*/
matchedCount: Int64;
/**
* Number of documents modified.
*/
modifiedCount: Int64;
/**
* Number of documents deleted.
*/
deletedCount: Int64;
/**
* Number of documents upserted.
*/
upsertedCount: Int64;
/**
* Map of the index of the operation to the id of the upserted document.
*/
upsertedIds: Map<Int64, any>;
}
/**
* Note: this class is "NOT REQUIRED" since all of its fields are marked
* "NOT REQUIRED". Drivers that do not implement this class SHOULD use void
* as the return type for insertOne.
*/
class InsertOneResult {
/**
* Indicates whether this write result was acknowledged. If not, then all
* other members of this result will be undefined.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
acknowledged: Boolean;
/**
* The identifier that was inserted. If the server generated the identifier, this value
* will be null as the driver does not have access to that data.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
insertedId: any;
}
/**
* Note: this class is "NOT REQUIRED" since all of its fields are marked
* "NOT REQUIRED". Drivers that do not implement this class SHOULD use void
* as the return type for insertMany.
*/
class InsertManyResult {
/**
* Indicates whether this write result was acknowledged. If not, then all
* other members of this result will be undefined.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
acknowledged: Boolean;
/**
* Map of the index of the inserted document to the id of the inserted document.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
insertedIds: Map<Int64, any>;
}
class DeleteResult {
/**
* Indicates whether this write result was acknowledged. If not, then all
* other members of this result will be undefined.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
acknowledged: Boolean;
/**
* The number of documents that were deleted.
*/
deletedCount: Int64;
}
class UpdateResult {
/**
* Indicates whether this write result was acknowledged. If not, then all
* other members of this result will be undefined.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
acknowledged: Boolean;
/**
* The number of documents that matched the filter.
*/
matchedCount: Int64;
/**
* The number of documents that were modified.
*/
modifiedCount: Int64;
/**
* The number of documents that were upserted.
*
* NOT REQUIRED: Drivers may choose to not provide this property so long as
* it is always possible to infer whether an upsert has taken place. Since
* the "_id" of an upserted document could be null, a null "upsertedId" may
* be ambiguous in some drivers. If so, this field can be used to indicate
* whether an upsert has taken place.
*/
upsertedCount: Int64;
/**
* The identifier of the inserted document if an upsert took place.
*/
upsertedId: any;
}
Error Handling
Defined below are error and exception types that should be reported from the various write methods. Since error types across languages would be impossible to reconcile, the below definitions represent the fields and names for the information that should be present. Structure isn't important as long as the information is available.
Drivers SHOULD report errors however they report other server errors: by raising an exception, returning "false" and populating an error struct, or another idiom that is consistent with other server errors.
WriteConcernError
class WriteConcernError {
/**
* An integer value identifying the write concern error. Corresponds to the
* "writeConcernError.code" field in the command response.
*
* @see https://www.mongodb.com/docs/manual/reference/method/WriteResult/
*/
code: Int32;
/**
* A document identifying the write concern setting related to the error.
* Corresponds to the "writeConcernError.errInfo" field in the command
* response.
*
* @see https://www.mongodb.com/docs/manual/reference/method/WriteResult/
*/
details: Document;
/**
* A description of the error. Corresponds to the
* "writeConcernError.errmsg" field in the command response.
*
* @see https://www.mongodb.com/docs/manual/reference/method/WriteResult/
*/
message: String;
}
Drivers MUST construct a WriteConcernError
from a server reply as follows:
- Set
code
towriteConcernError.code
. - Set
message
towriteConcernError.errmsg
if available. - Set
details
towriteConcernError.errInfo
if available. Drivers MUST NOT parse insideerrInfo
.
See writeConcernError Examples in the Read/Write Concern spec for examples of how a server represents write concern errors in replies.
WriteError
Write errors for insert
, update
, and delete
commands are reported as objects within a writeErrors
array field in
the command response. Drivers MUST construct a WriteError
from a server reply as follows (where writeErrors[]
refers
to a particular element in the array):
- Set
code
towriteErrors[].code
. - Set
message
towriteErrors[].errmsg
if available. - Set
details
towriteErrors[].errInfo
if available. Drivers MUST NOT parse insideerrInfo
.
For single-statement writes (i.e. insertOne
, updateOne
, updateMany
, replaceOne
, deleteOne
, and deleteMany
),
a single write error may be reported in the array and writeErrors[0].index
will be zero.
For multi-statement writes (i.e. insertMany
and bulkWrite
), potentially many write errors may be reported in the
array and the index
property will be set accordingly. Since the reported index
is specific to each command, drivers
MUST adjust the index accordingly for BulkWriteError.index
.
class WriteError {
/**
* An integer value identifying the write error. Corresponds to the
* "writeErrors[].code" field in the command response.
*
* @see https://www.mongodb.com/docs/manual/reference/method/WriteResult/
*/
code: Int32;
/**
* A document providing more information about the write error (e.g. details
* pertaining to document validation). Corresponds to the
* "writeErrors[].errInfo" field in the command response.
*
* @see https://www.mongodb.com/docs/manual/reference/method/WriteResult/
*/
details: Document;
/**
* A description of the error. Corresponds to the "writeErrors[].errmsg"
* field in the command response.
*
* @see https://www.mongodb.com/docs/manual/reference/method/WriteResult/
*/
message: String;
}
class BulkWriteError : WriteError {
/**
* The index of the request that errored. This is derived in part from the
* "writeErrors[].index" field in the command response; however, drivers
* MUST adjust the index accordingly for bulk writes that execute multiple
* writes commands.
*/
index: Int32;
/**
* The request that errored.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
request: Optional<WriteModel>;
}
/**
* NOTE: Only one of writeConcernError or writeError will be populated at a time. Your driver must present the offending
* error to the user.
*/
class WriteException {
/**
* The error that occurred on account of write concern failure.
*/
writeConcernError: Optional<WriteConcernError>;
/**
* The error that occurred on account of a non-write concern failure.
*/
writeError: Optional<WriteError>;
}
class BulkWriteException {
/**
* The requests that were sent to the server.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
processedRequests: Optional<Iterable<WriteModel>>;
/**
* The requests that were not sent to the server.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
unprocessedRequests: Optional<Iterable<WriteModel>>;
/**
* The intermediary write result for any operations that succeeded before
* the bulk write was interrupted.
*
* NOT REQUIRED: Drivers may choose to not provide this property.
*/
writeResult: Optional<BulkWriteResult>;
/**
* The error that occurred on account of write concern failure. If the error was a Write Concern related, this field must be present.
*/
writeConcernError: Optional<WriteConcernError>;
/**
* The error that occurred on account of a non-write concern failure. This might be empty if the error was a Write Concern related error.
*/
writeErrors: Optional<Iterable<BulkWriteError>>;
}
Find And Modify
interface Collection {
/**
* Finds a single document and deletes it, returning the original. The document to return may be null.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
* @throws WriteException
*/
findOneAndDelete(filter: Document, options: Optional<FindOneAndDeleteOptions>): Optional<Document>;
/**
* Finds a single document and replaces it, returning either the original or the replaced
* document. The document to return may be null.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
* @throws WriteException
*/
findOneAndReplace(filter: Document, replacement: Document, options: Optional<FindOneAndReplaceOptions>): Optional<Document>;
/**
* Finds a single document and updates it, returning either the original or the updated
* document. The document to return may be null.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
* @throws WriteException
*/
findOneAndUpdate(filter: Document, update: (Document | Document[]), options: Optional<FindOneAndUpdateOptions>): Optional<Document>;
}
enum ReturnDocument {
/**
* Indicates to return the document before the update, replacement, or insert occurred.
*/
BEFORE,
/**
* Indicates to return the document after the update, replacement, or insert occurred.
*/
AFTER
}
class FindOneAndDeleteOptions {
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.4. Older servers >= 4.2 will report an error for using this option.
* For servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes and servers < 4.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
hint: Optional<(String | Document)>;
/**
* The maximum amount of time to allow the query to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
maxTimeMS: Optional<Int64>;
/**
* Limits the fields to return for all matching documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* Note: this option is mapped to the "fields" findAndModify command option.
*
* @see https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results
*/
projection: Optional<Document>;
/**
* Determines which document the operation modifies if the query selects multiple documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
sort: Optional<Document>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
let: Optional<Document>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for findAndModify command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
}
class FindOneAndReplaceOptions {
/**
* If true, allows the write to opt-out of document level validation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.4. Older servers >= 4.2 will report an error for using this option.
* For servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes and servers < 4.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
hint: Optional<(String | Document)>;
/**
* The maximum amount of time to allow the query to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
maxTimeMS: Optional<Int64>;
/**
* Limits the fields to return for all matching documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* Note: this option is mapped to the "fields" findAndModify command option.
*
* @see https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results
*/
projection: Optional<Document>;
/**
* When ReturnDocument.After, returns the replaced or inserted document rather than the original.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* Note: this option is mapped to the "new" findAndModify boolean field. ReturnDocument.Before represents false,
* and ReturnDocument.After represents true.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
returnDocument: Optional<ReturnDocument>;
/**
* Determines which document the operation modifies if the query selects multiple documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
sort: Optional<Document>;
/**
* When true, findAndModify creates a new document if no document matches the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
upsert: Optional<Boolean>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
let: Optional<Document>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for findAndModify command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
}
class FindOneAndUpdateOptions {
/**
* A set of filters specifying to which array elements an update should apply.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.6, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/update/
*/
arrayFilters: Optional<Array<Document>>;
/**
* If true, allows the write to opt-out of document level validation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.2, this option is ignored and not sent as document validation is not available.
*/
bypassDocumentValidation: Optional<Boolean>;
/**
* Specifies a collation.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* For servers < 3.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
collation: Optional<Document>;
/**
* The index to use. Specify either the index name as a string or the index key pattern.
* If specified, then the query system will only consider plans using the hinted index.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 4.4. Older servers >= 4.2 will report an error for using this option.
* For servers < 4.2, the driver MUST raise an error if the caller explicitly provides a value.
* For unacknowledged writes and servers < 4.4, the driver MUST raise an error if the caller explicitly provides a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
hint: Optional<(String | Document)>;
/**
* The maximum amount of time to allow the query to run.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
maxTimeMS: Optional<Int64>;
/**
* Limits the fields to return for all matching documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* Note: this option is mapped to the "fields" findAndModify command option.
*
* @see https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results
*/
projection: Optional<Document>;
/**
* When ReturnDocument.After, returns the replaced or inserted document rather than the original.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* Note: this option is mapped to the "new" findAndModify boolean field. ReturnDocument.Before represents false,
* and ReturnDocument.After represents true.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
returnDocument: Optional<ReturnDocument>;
/**
* Determines which document the operation modifies if the query selects multiple documents.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
sort: Optional<Document>;
/**
* When true, creates a new document if no document matches the query.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
upsert: Optional<Boolean>;
/**
* Map of parameter names and values. Values must be constant or closed
* expressions that do not reference document fields. Parameters can then be
* accessed as variables in an aggregate expression context (e.g. "$$var").
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
* This option is only supported by servers >= 5.0. Older servers >= 2.6 (and possibly earlier) will report an error for using this option.
*
* @see https://www.mongodb.com/docs/manual/reference/command/findAndModify/
*/
let: Optional<Document>;
/**
* Enables users to specify an arbitrary comment to help trace the operation through
* the database profiler, currentOp and logs. The default is to not send a value.
*
*
* The comment can be any valid BSON type for server versions 4.4 and above.
* Server versions prior to 4.4 do not support comment for findAndModify command,
* and providing one will result in a server-side error.
*/
comment: Optional<any>;
}
Update vs. Replace Validation
The update
family of operations require that the update document parameter MUST have only atomic modifiers. In
practice, this means that introspection needs to happen on that document to enforce this. However, it is enough to only
check the first element in the document. If it begins with a $
sign and the rest of the document's elements do not,
the server will throw an error. Note that it is required that an update document have at least one atomic modifier.
The replace
family of operations require that the replacement document parameter MUST NOT begin with an atomic
modifier. In practice, this means that introspection needs to happen on that document to enforce this. However, it is
enough to only check the first element in the document. If it does not begin with a $
sign but an element later on
does, the server will throw an error.
Aggregation Pipelines with Write Stages
This section discusses special considerations for aggregation pipelines that contain write stages (e.g. $out
,
$merge
).
Returning a cursor on the output collection
As noted in the documentation for the aggregate
helper earlier in this document, $out
and $merge
are special
pipeline stages that cause no results to be returned from the server. As such, drivers MAY setup a cursor to be executed
upon iteration against the output collection and return that instead of an iterable that would otherwise have no
results.
Drivers that do so for $merge
MAY remind users that such a cursor may return more documents than were written by the
aggregation (e.g. documents that existed in the collection prior to $merge
being executed).
Read preferences and server selection
This section is only applicable if an explicit (i.e. per-operation) or inherited (e.g. from a Collection) read
preference is available and it is not a primary read preference (i.e. { "mode": "primary" }
).
Historically, only primaries could execute an aggregation pipeline with $out
or $merge
and drivers never considered
a read preference for the operation. As of featureCompatibilityVersion
4.4, secondaries can now execute pipelines with
$out
or $merge
. Since drivers do not track featureCompatibilityVersion
, the decision to consider a read preference
for such a pipeline will depend on the wire version(s) of the server(s) to which the driver is connected.
If there are one or more available servers and one or more of those servers is pre-5.0 (i.e. wire version < 13), drivers MUST NOT use the available read preference and MUST instead select a server using a primary read preference.
Otherwise, if there are either no available servers, all available servers are 5.0+ (i.e. wire version >= 13), or the topology type is LoadBalanced (we can assume the backing mongos is 5.0+), drivers MUST use the available read preference.
Drivers SHOULD augment their server selection algorithm such that this logic can be enforced within a single server selection attempt.
Drivers MUST discern the read preference used to select a server for the operation, which SHALL be used for specifying the $readPreference global command argument and passing read preference to mongos and load balancers (if applicable).
Explain
[!NOTE] Explain helpers are optional. Drivers that do not provide explain helpers may ignore this section.
interface ExplainOptions {
/**
* The maximum amount of time to allow the explain to run.
*
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
*
* NOTE: This option is deprecated in favor of timeoutMS.
*/
maxTimeMS: Optional<Int64>;
}
Drivers MUST ensure that its helper permits users to specify a timeout (maxTimeMS or timeoutMS) for the explain command specifically. An example, using Node, might look like:
collection.find({ name: 'john doe' }).explain({ maxTimeMS: 1000 });
// sends:
{
explain: { find: <collection>, query: { name: 'john doe' } },
maxTimeMS: 1000
}
collection.find({ name: 'john doe' }).explain({ timeoutMS: 1000 });
// sends:
{
explain: { find: <collection>, query: { name: 'john doe' } },
maxTimeMS: <1000 - min rtt>
}
Drivers MUST document how users can specify options on their explain helpers.
Test Plan
See the README for tests.
Motivation
Current drivers have chosen slightly different names and semantics for the same operations and options. In addition, not all drivers offer all the same operations and methods. As such, it is difficult to transition from driver to driver making the jobs of polyglot developers, documentation authors, and support engineers more difficult.
Backwards Compatibility
This spec should be mostly backwards compatible as it is very lenient. Drivers finding a backwards compatibility problem should attempt to work around it using an acceptable deviation. In rare cases, a driver may need to break backwards compatibility. This should be done in accordance with a versioning scheme indicating that a backwards compatible break may have occurred in conjunction with release documentation and warnings.
Reference Implementation
See Test Plan
Related Terminology
If a driver needs to refer to items in the following list, the below are the accepted forms of those terms and deviations from the Naming section are still permissible.
- Read Preference: readPreference
- Read Concern: readConcern
- Write Concern: writeConcern
Q & A
Q: Why do the names of the fields differ from those defined in the MongoDB manual?
Documentation and commands often refer to same-purposed fields with different names making it difficult to have a cohesive API. In addition, occasionally the name was correct at one point and its purpose has expanded to a point where the initial name doesn't accurately describe its current function.
In addition, responses from the servers are sometimes cryptic and used for the purposes of compactness. In these cases, we felt the more verbose form was desirable for self-documentation purposes.
Q: Where is read preference?
Read preference is about selecting a server with which to perform a read operation, such as a query, a count, or an aggregate. Since all operations defined in this specification are performed on a collection, it's uncommon that two different read operations on the same collection would use a different read preference, potentially getting out-of-sync results. As such, the most natural place to indicate read preference is on the client, the database, or the collection itself and not the operations within it.
However, it might be that a driver needs to expose this selection filter to a user per operation for various reasons. As noted before, it is permitted to specify this, along with other driver-specific options, in some alternative way.
Q: Where is read concern?
Read concern is about indicating how reads are handled. Since all operations defined in this specification are performed on a collection, it's uncommon that two different read operations on the same collection would use a different read concern, potentially causing mismatched and out-of-sync data. As such, the most natural place to indicate read concern is on the client, the database, or the collection itself and not the operations within it.
However, it might be that a driver needs to expose read concern to a user per operation for various reasons. As noted before, it is permitted to specify this, along with other driver-specific options, in some alternative way.
Q: Where is write concern?
Write concern is about indicating how writes are acknowledged. Since all operations defined in this specification are performed on a collection, it's uncommon that two different write operations on the same collection would use a different write concern, potentially causing mismatched and out-of-sync data. As such, the most natural place to indicate write concern is on the client, the database, or the collection itself and not the operations within it. See the Read/Write Concern specification for the API of constructing a read/write concern and associated API.
However, it might be that a driver needs to expose write concern to a user per operation for various reasons. As noted before, it is permitted to specify this, along with other driver-specific options, in some alternative way.
Q: How do I throttle unacknowledged writes now that write concern is no longer defined on a per operation basis?
Some users used to throttle unacknowledged writes by using an acknowledged write concern every X number of operations. Going forward, the proper way to handle this is by using the bulk write API.
Q: What is the logic for adding "One" or "Many" into the method and model names?
If the maximum number of documents affected can only be one, we added "One" into the name. This makes it explicit that the maximum number of documents that could be affected is one vs. infinite.
In addition, the current API exposed by all our drivers has the default value for "one" or "many" set differently for update and delete. This generally causes some issues for new developers and is a minor annoyance for existing developers. The safest way to combat this without introducing discrepancies between drivers/driver versions or breaking backwards compatibility was to use multiple methods, each signifying the number of documents that could be affected.
Q: What considerations have been taken for the eventual merging of query and the aggregation framework?
In the future, it is probable that a new query engine (QE) will look very much like the aggregation framework. Given
this assumption, we know that both find
and aggregate
will be renderable in QE, each maintaining their ordering
guarantees for full backwards compatibility.
Hence, the only real concern is how to initiate a query using QE. While find
is preferable, it would be a backwards
breaking change. It might be decided that find
is what should be used, and all drivers will release major revisions
with this backwards breaking change. Alternatively, it might be decided that another initiator would be used.
Q: Didn't we just build a bulk API?
Yes, most drivers did just build out a bulk API (fluent-bulk-api). While unfortunate, we felt it better to have the bulk api be consistent with the rest of the methods in the CRUD family of operations. However, the fluent-bulk-api is still able to be used as this change is non-backwards breaking. Any driver which implemented the fluent bulk API should deprecate it and drivers that have not built it should not do so.
Q: Should drivers offer explain helpers?
Originally, it was determined that explain should not be exposed via
specialized APIs in drivers because it it was deemed to be an unusual use-case for a driver. We'd like users to use the
shell for this purpose. However, explain is still possible from a driver. Some drivers have historically provided
explain helpers and continue to do so. Drivers that do not offer explain helpers can run explain commands using the
runCommand API.
Q: What about explain?
Explain has been determined to be not a normal use-case for a driver. We'd like users to use the shell for this purpose. However, explain is still possible from a driver. For find, it can be passed as a modifier. Aggregate can be run using a runCommand method passing the explain option. In addition, server 3.0 offers an explain command that can be run using a runCommand method.
Q: Where did modifiers go in FindOptions?
MongoDB 3.2 introduced the find command. As opposed to using the general "modifiers" field any longer, each relevant option is listed explicitly. Some options, such as "tailable" or "singleBatch" are not listed as they are derived from other fields. Upgrading a driver should be a simple procedure of deprecating the "modifiers" field and introducing the new fields. When a collision occurs, the explicitly specified field should override the value in "modifiers".
Q: Where is save
?
Drivers have historically provided a save
method, which was syntactic sugar for upserting or inserting a document
based on whether it contained an identifier, respectively. While the save
method may be convenient for interactive
environments, such as the shell, it was intentionally excluded from the CRUD specification for language drivers for
several reasons. The save
method promotes a design pattern of "fetch, modify, replace" and invites race conditions in
application logic. Additionally, the split nature of save
makes it difficult to discern at a glance if application
code will perform an insert or potentially dangerous full-document replacement. Instead of relying on save
,
application code should know whether document already has an identifier and explicitly call insertOne
or replaceOne
with the upsert
option.
Q: Where is useCursor
in AggregateOptions?
Inline aggregation results are no longer supported in server 3.5.2+. The
aggregate command must be provided either the
cursor
document or the explain
boolean. AggregateOptions does not define an explain
option. If a driver does
support an explain
option, the cursor
document should be omitted if explain
is true
. Otherwise a cursor
document must be added to the aggregate
command. Regardless, useCursor
is no longer needed. Removing useCursor
is
a backwards breaking change, so drivers should first deprecate this option in a minor release, and remove it in a major
release.
Q: Where is singleBatch
in FindOptions?
Drivers have historically allowed users to request a single batch of results (after which the cursor is closed) by
specifying a negative value for the limit
option. For servers < 3.2, a single batch may be requested by specifying a
negative value in the numberToReturn
wire protocol field. For servers >= 3.2, the find
command defines limit
as a
non-negative integer option but introduces a singleBatch
boolean option. Rather than introduce a singleBatch
option
to FindOptions, the spec preserves the existing API for limit
and instructs drivers to convert negative values
accordingly for servers >= 3.2.
Q: Why are client-side errors raised for some unsupported options?
Server versions before 3.4 were inconsistent about reporting errors for unrecognized command options and may simply ignore them, which means a client-side error is the only way to inform users that such options are unsupported. For unacknowledged writes using OP_MSG, a client-side error is necessary because the server has no chance to return a response (even though a 3.6+ server is otherwise capable of reporting errors for unrecognized options). For unacknowledged writes using legacy opcodes (i.e. OP_INSERT, OP_UPDATE, and OP_DELETE), the message body has no field with which to express these options so a client-side error is the only mechanism to inform the user that such options are unsupported. The spec does not explicitly refer to unacknowledged writes using OP_QUERY primarily because a response document is always returned and drivers generally would not consider using OP_QUERY precisely for that reason.
Q: Why does reverting to using count
instead of aggregate
with $collStats
for estimatedDocumentCount not require a
major version bump in the drivers, even though it might break users of the Stable API?
SemVer
allows
for a library to include a breaking change in a minor or patch version if the change is required to fix another
accidental breaking change introduced in a prior version and is not expected to further break a large number of users.
Given that the original switch to $collStats
was a breaking change due to it not working on views, the number of users
using estimatedDocumentCount with apiStrict: true
is small, and the server is back-porting the addition of count
to
the Stable API, it was decided that this change was acceptable to make in minor version releases of the drivers per the
aforementioned allowance in the SemVer spec.
Changelog
-
2024-11-13: Define
findOne
operation as optional, and add guidance onlimit
andbatchSize
forfind
operations. -
2024-11-04: Always send a value for
bypassDocumentValidation
if it was specified. -
2024-11-01: Add hint to DistinctOptions
-
2024-10-30: Document query limitations in
countDocuments
. -
2024-10-28: Clarified that generated identifiers should be prepended to documents.
-
2024-10-01: Add sort option to
replaceOne
andupdateOne
. -
2024-09-12: Specify that explain helpers support maxTimeMS.
-
2024-02-20: Migrated from reStructuredText to Markdown.
-
2022-10-05: Remove spec front matter and reformat changelog.
-
2022-04-21: Revert to using the
count
command forestimatedDocumentCount
-
2022-02-18: Add let to BulkWriteOptions.
-
2022-02-10: Specified that
getMore
command must explicitly send inherited comment. -
2022-02-01: Add comment attribute to all helpers.
-
2022-01-27: Use optional return types for write commands and findAndModify
-
2022-01-19: Deprecate the maxTimeMS option and require that timeouts be applied per the client-side operations timeout spec.
-
2022-01-14: Add let to ReplaceOptions
-
2021-11-10: Revise rules for applying read preference for aggregations with $out and $merge. Add let to FindOptions, UpdateOptions, DeleteOptions, FindOneAndDeleteOptions, FindOneAndReplaceOptions, FindOneAndUpdateOptions
-
2021-09-28: Support aggregations with $out and $merge on 5.0+ secondaries
-
2021-08-31: Allow unacknowledged hints on write operations if supported by server (reverts previous change).
-
2021-06-02: Introduce WriteError.details and clarify WriteError construction
-
2021-06-01: Add let to AggregateOptions
-
2021-01-21: Update estimatedDocumentCount to use $collStats stage for servers >= 4.9
-
2020-04-17: Specify that the driver must raise an error for unacknowledged hints on any write operation, regardless of server version.
-
2020-03-19: Clarify that unacknowledged update, findAndModify, and delete operations with a hint option should raise an error on older server versions.
-
2020-03-06: Added hint option for DeleteOne, DeleteMany, and FindOneAndDelete operations.
-
2020-01-24: Added hint option for findAndModify update/replace operations.
-
2020-01-17: Add allowDiskUse to FindOptions.
-
2020-01-14: Deprecate oplogReplay option for find command
-
2020-01-10: Clarify client-side error reporting for unsupported options
-
2020-01-10: Error if hint specified for unacknowledged update using OP_UPDATE or OP_MSG for servers < 4.2
-
2019-10-28: Removed link to old language examples.
-
2019-09-26: Added hint option for update commands.
-
2019-06-07: Consistent treatment for aggregate $merge and $out stages
-
2019-05-01: Specify a document or pipeline for commands with updates in server 4.2+.
-
2019-02-20: Mark the request field of BulkWriteError as NOT REQUIRED
-
2018-11-30: Specify maxAwaitTimeMS in AggregateOptions
-
2018-11-15: Aggregate commands with an $out stage should not specify batchSize
-
2018-10-25: Note how results are backed for aggregate, distinct, and find operations
-
2018-07-25: Added upsertedCount to UpdateResult.
-
2018-06-07: Deprecated the count helper. Added the estimatedDocumentCount and countDocuments helpers.
-
2018-03-05: Deprecate snapshot option
-
2018-03-01: Deprecate maxScan query option.
-
2018-02-06: Note that batchSize in FindOptions and AggregateOptions should also apply to getMore.
-
2018-01-26: Only send bypassDocumentValidation option if it's true, don't send false.
-
2017-10-23: Allow BulkWriteException to provide an intermediary write result.
-
2017-10-17: Document negative limit for FindOptions.
-
2017-10-09: Bumped minimum server version to 2.6 and removed references to older versions in spec and tests.
-
2017-10-09: Prohibit empty insertMany() and bulkWrite() operations.
-
2017-10-09: Split UpdateOptions and ReplaceOptions. Since replaceOne() previously used UpdateOptions, this may have BC implications for drivers using option classes.
-
2017-10-05: Removed useCursor option from AggregateOptions.
-
2017-09-26: Added hint option to AggregateOptions.
-
2017-09-25: Added comment option to AggregateOptions.
-
2017-08-31: Added arrayFilters to bulk write update models.
-
2017-06-29: Remove requirement of using OP_KILL_CURSOR to kill cursors.
-
2017-06-27: Added arrayFilters to UpdateOptions and FindOneAndUpdateOptions.
-
2017-06-26: Added FAQ entry for omission of save method.
-
2017-05-12: Removed extra "collation" option added to several bulk write models.
-
2017-01-09: Removed modifiers from FindOptions and added in all options.
-
2017-01-09: Changed the value type of FindOptions.skip and FindOptions.limit to Int64 with a note related to calculating batchSize for opcode writes.
-
2017-01-09: Reworded description of how default values are handled and when to send certain options.
-
2016-09-23: Included collation option in the bulk write models.
-
2016-08-05: Added in collation option.
-
2015-11-05: Typos in comments about bypassDocumentValidation
-
2015-10-16: Added maxAwaitTimeMS to FindOptions.
-
2015-10-01: Moved bypassDocumentValidation into BulkWriteOptions and removed it from the individual write models.
-
2015-09-16: Added bypassDocumentValidation.
-
2015-09-16: Added readConcern notes.
-
2015-06-17: Added limit/batchSize calculation logic.