Skip to content

BUCKET.UPDATE

Updates documents in a bucket that match a filter expression.

BUCKET.UPDATE <bucket> <query> <update> [SORTBY <field> <ASC|DESC>] [BATCH <n>] [LIMIT <n>] [COLLATION <spec>] [NAMESPACE <path>] [CLOSE]

Keyword names are not case-sensitive, and each keyword can appear at most once.

ArgumentTypeRequiredDescription
bucketstringYesName of the bucket to update.
queryJSON or BSONYesFilter expression to match documents. Use {} to match all documents.
updateJSON or BSONYesUpdate document with update operators. Cannot be empty.
SORTBYstring + directionNoProcess documents in sorted order. Requires field name followed by ASC or DESC.
BATCHintegerNoMaximum number of documents to update per batch. Must be non-negative. It does not cap the total number of results, use LIMIT for that. Use BUCKET.ADVANCE to get the next batch.
LIMITintegerNoMaximum total number of documents the cursor updates across the first call and all BUCKET.ADVANCE calls. Must be non-negative. 0 means no limit (default). When the limit is reached, the response carries cursor_id -1 and the cursor is removed. An upsert counts as one document.
COLLATIONJSONNoQuery-level collation spec for locale-aware string comparison. Overrides index collation for this query.
NAMESPACEstringNoRun this command in the given namespace instead of the session’s current one. The namespace must exist. The session’s current namespace does not change. A cursor opened this way stays in that namespace for BUCKET.ADVANCE.
CLOSEflagNoClose the cursor when the command returns. The command updates the first batch and the response carries cursor_id -1. Takes no value.

The command returns a cursor ID and an array of ObjectIds for updated documents. The format depends on the protocol version.

An ObjectId is a 12-byte unique identifier. The encoding format of returned ObjectIds depends on the session’s object_id_format setting:

FormatResponse TypeDescription
hexString24-character hex-encoded string (default)
bytesBinaryRaw 12-byte array

To change the format:

SESSION.ATTRIBUTE SET object_id_format hex
SESSION.ATTRIBUTE SET object_id_format bytes

RESP3 (map format):

1# "cursor_id" => (integer) <cursor-id>
2# "object_ids" => 1) "6835a1c0e4b0f72a3c000001"
2) "6835a1c0e4b0f72a3c000002"
...

RESP2 (array format):

1) (integer) <cursor-id>
2) 1) "6835a1c0e4b0f72a3c000001"
2) "6835a1c0e4b0f72a3c000002"
...

When no documents match the filter, the object_ids array is empty.

The object_ids array contains only the documents that were actually modified. A matched document whose update would leave its content unchanged is not modified and does not appear in object_ids.

Auto-commit mode (default):

The update is committed immediately.

Transaction mode (within BEGIN/COMMIT):

The update is not committed until COMMIT is called. Use ROLLBACK to cancel the update operation.

The update argument accepts a JSON or BSON document containing one or more of the following operators:

$set: Sets field values on matched documents.

'{"$set": {"status": "active", "version": 2}}'

The _id field is immutable and cannot be modified with $set.

$unset: Removes fields from matched documents. Accepts either an array of field names or a document with field names as keys:

'{"$unset": ["temporary_field", "deprecated_field"]}'
'{"$unset": {"temporary_field": 1, "deprecated_field": 1}}'

array_filters: Applies conditional updates to array elements using positional operators. Each filter is a document with an identifier and a condition.

Supported filter operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $all, $size, $exists.

'{"$set": {"grades.$[elem].score": 100}, "array_filters": [{"elem": {"$gte": 8}}]}'

Positional operators target array elements. If the target field is missing or is not an array, the document is left unchanged.

upsert: Boolean. When true, inserts a new document if no documents match the filter. Positional operators cannot be used with upsert.

'{"$set": {"status": "active"}, "upsert": true}'

After an update, all indexes whose selectors overlap the modified field paths are synchronized with the new document content.

When using BATCH, use the cursor ID with BUCKET.ADVANCE to update more matching documents:

BUCKET.ADVANCE UPDATE <cursor-id>

Each call updates the next batch of documents up to the batch size.

BATCH caps a single call, LIMIT caps the whole cursor. Each call updates at most the smaller of BATCH and the remaining LIMIT. The call that reaches the limit returns cursor_id -1 and removes the cursor from the session. There is no need to call BUCKET.CLOSE on it. A document inserted by upsert counts as one toward the limit.

When one batch is enough, send the command with CLOSE. The command updates the first batch, returns cursor_id -1, and leaves no cursor in the session.

The command must be sent to the primary of at least one shard assigned to the bucket. Any other member, including a standby, rejects the request with a redirect to the primary. Use BUCKET.LOCATE to find it.

Argument errors:

Error CodeError messageCause
ERRupdate argument cannot be empty-
ERRupdate document cannot be an empty document-
ERRBATCH argument must be followed by a non-negative integer-
ERRLIMIT argument must be followed by a non-negative integer-
ERRUnknown sort direction: '<value>'The SORTBY direction is not ASC or DESC.
ERRUnknown '<keyword>' argument-
ERRDuplicate '<keyword>' argument-
ERRNAMESPACE argument must be followed by a namespace-

Namespace errors:

Error CodeError messageCause
NOSUCHNAMESPACENo such namespace: '<path>'-
NAMESPACEBEINGREMOVEDNamespace '<path>' is being removed-

Bucket errors:

Error CodeError messageCause
NOSUCHBUCKETNo such bucket: '<bucket>'-
BUCKETBEINGREMOVEDBucket '<bucket>' is being removed-
REJECT<shardId> <host>:<port>This member is not the primary of any of the bucket’s shards. The message carries the primary’s address.
DUPLICATEKEYDuplicate key: _id '<hex>'A duplicate _id was found during upsert.

Index errors:

Error CodeError messageCause
INDEXTYPE_MISMATCHIndex type mismatch: index '<index>' expects '<type>', but selector '<selector>' matched a value of type '<actual>'-
VECTORINDEXNOTREADYVector index '<namespace>/<bucket>/<indexId>' is not ready yetThe vector index is still being built or recovered. Retry after the background build completes.

Update with $set:

BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}'

Update with $unset:

BUCKET.UPDATE users '{"age": {"$gt": 30}}' '{"$unset": ["temporary_field", "deprecated_field"]}'

Update with $set and $unset:

BUCKET.UPDATE users '{}' '{"$set": {"version": 2}, "$unset": ["old_field"]}'

Update with array_filters:

BUCKET.UPDATE students '{}' '{"$set": {"grades.$[elem].passed": true}, "array_filters": [{"elem": {"$gte": 60}}]}'

Update with upsert:

BUCKET.UPDATE users '{"username": "alice"}' '{"$set": {"username": "alice", "status": "active"}, "upsert": true}'

Update with sorting:

BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}' SORTBY created_at ASC

Update with a batch size:

BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}' BATCH 50

Update with a total limit:

BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}' BATCH 50 LIMIT 120

Updates at most 120 documents in total. The first two calls update 50 each, the third updates 20 and returns cursor_id -1.

Update that closes its cursor:

> BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}' BATCH 50 CLOSE
1# "cursor_id" => (integer) -1
2# "object_ids" => ... (first 50 updated)

Update with collation:

BUCKET.UPDATE users '{"name": "alice"}' '{"$set": {"verified": true}}' COLLATION '{"locale": "en", "strength": 2}'

Updates documents matching "alice" using case-insensitive English collation.

Batch update with pagination:

> BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}' BATCH 100
1# "cursor_id" => (integer) 1
2# "object_ids" =>... (first 100 updated)
> BUCKET.ADVANCE UPDATE 1
1# "cursor_id" => (integer) 1
2# "object_ids" => ... (next 100 updated)

Batch update with a limit:

> BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}' BATCH 2 LIMIT 3
1# "cursor_id" => (integer) 2
2# "object_ids" => ... (2 updated)
> BUCKET.ADVANCE UPDATE 2
1# "cursor_id" => (integer) -1
2# "object_ids" => ... (1 updated)
> BUCKET.ADVANCE UPDATE 2
(error) ERR No previous query context found for 'update' operation with the given cursor id

Update within a transaction:

BEGIN
BUCKET.UPDATE users '{"status": "pending"}' '{"$set": {"status": "active"}}'
COMMIT