Update Arrays in a Document

For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt

Update Arrays in a Document

Overview

In this guide, you can learn how to update array elements in one or more documents.

To update elements in an array, perform the following actions:

  • Provide an [update document](https://www.mongodb.com/docs/drivers/go/current/crud/update.md#std-label-golang-update-document that specifies the update.

  • Specify which array elements to update.

  • Perform the update using an update operation with these specifications.

Sample Data

The examples in this guide use the following Drink struct as a model for documents in the drinks collection:

type Drink struct {
    Description string
    Sizes       []int32 `bson:"sizes,truncate"`
    Styles      []string
}

The truncate [struct tag](https://www.mongodb.com/docs/drivers/go/current/data-formats/bson.md#std-label-golang-struct-tags allows the driver to truncate types such as float64 to int32 when unmarshalling.

To run the examples in this guide, load the sample data into the db.drinks collection with the following snippet:

coll := client.Database("db").Collection("drinks")
docsToInsert := []any{
    Drink{Description: "Matcha Latte", Sizes: []int32{12, 16, 20}, Styles: []string{"iced", "hot", "extra hot"}},
}

result, err := coll.InsertMany(context.TODO(), docsToInsert)

Each document contains a description of a drink that includes the drink's description, available sizes in ounces, and available preparation styles, corresponding to the description, sizes, and styles fields in each document.

Tip: Nonexistent Databases and Collections

If the necessary database and collection don't exist when you perform a write operation, the server implicitly creates them.

The following examples use the FindOneAndUpdate() method to retrieve and update a document and to return the state of the document after the update occurs. If you want to update multiple documents with an array field, use the UpdateMany() method.

Specify Array Elements

To specify which array elements to update, use a positional operator. Positional operators can specify the [first](https://www.mongodb.com/docs/drivers/go/current/crud/update/embedded-arrays.md#std-label-golang-first-element, [multiple](https://www.mongodb.com/docs/drivers/go/current/crud/update/embedded-arrays.md#std-label-golang-multiple-elements, or [all](https://www.mongodb.com/docs/drivers/go/current/crud/update/embedded-arrays.md#std-label-golang-all-elements array elements to update.

To specify array elements with a positional operator, use dot notation. Dot notation is a property access syntax for navigating array elements and fields of an embedded document.

First Array Element

To update the first array element that matches your query filter, use the positional $ operator. The query filter must be for the array field.

Example

This example performs the following actions:

  • Matches array elements in sizes where the value is less than or equal to 16.

  • Decrements the first matching array value by 2.

filter := bson.D{{"sizes", bson.D{{"$lte", 16}}}}
update := bson.D{{"$inc", bson.D{{"sizes.$", -2}}}}
opts := options.FindOneAndUpdate().
    SetReturnDocument(options.After)

// Updates the first document that matches the filter
var updatedDoc Drink
err := coll.FindOneAndUpdate(context.TODO(), filter, update, opts).
    Decode(&updatedDoc)
if err != nil {
    panic(err)
}

// Prints the updated document
res, _ := bson.MarshalExtJSON(updatedDoc, false, false)
fmt.Println(string(res))

Output:

{"description":"Matcha Latte","sizes":[10,16,20],"styles":["iced","hot","extra hot"]}

Note:

In the preceding example, the query filter matches the values 12 and 16. Because the operation matches 12 first, it is the target of the update. To learn how to to update both matched values, see [Multiple Array Elements.](https://www.mongodb.com/docs/drivers/go/current/crud/update/embedded-arrays.md#std-label-golang-multiple-elements

Multiple Array Elements

To update multiple array elements that match your query filter, use the filtered positional $[<identifier>] operator. You must include an array filter in your update operation to specify which array elements to update.

The <identifier> is the name you use within your array filter. This value must begin with a lowercase letter and only contain alphanumeric characters.

Example

This example performs the following actions:

  • Creates an array filter with an identifier called hotOptions to match array elements that contain the string “hot”.

  • Applies the array filter by using the SetArrayFilters() method when creating a FindOneAndUpdateOptions instance.

  • Removes the values of these array elements by using the FindOneAndUpdate() method.

identifier := []any{bson.D{{"hotOptions", bson.D{{"$regex", "hot"}}}}}
update := bson.D{{"$unset", bson.D{{"styles.$[hotOptions]", ""}}}}
opts := options.FindOneAndUpdate().
    SetArrayFilters(identifier).
    SetReturnDocument(options.After)

// Updates the first document that matches the filter
var updatedDoc Drink
err := coll.FindOneAndUpdate(context.TODO(), bson.D{}, update, opts).
    Decode(&updatedDoc)
if err != nil {
    panic(err)
}

// Prints the updated document
res, _ := bson.MarshalExtJSON(updatedDoc, false, false)
fmt.Println(string(res))

Output:

{"description":"Matcha Latte","sizes":[12,16,20],"styles":["iced","",""]}

All Array Elements

To update all the array elements, use the all positional $[] operator.

Note:

If you specify a query filter for the array field, the positional $[] operator ignores the query filter and updates all the array elements.

Example

This example multiplies every array element in sizes by 29.57 to convert from ounces to milliliters:

identifier := []any{bson.D{{"hotOptions", bson.D{{"$regex", "hot"}}}}}
update := bson.D{{"$unset", bson.D{{"styles.$[hotOptions]", ""}}}}
opts := options.FindOneAndUpdate().
    SetArrayFilters(identifier).
    SetReturnDocument(options.After)

// Updates the first document that matches the filter
var updatedDoc Drink
err := coll.FindOneAndUpdate(context.TODO(), bson.D{}, update, opts).
    Decode(&updatedDoc)
if err != nil {
    panic(err)
}

// Prints the updated document
res, _ := bson.MarshalExtJSON(updatedDoc, false, false)
fmt.Println(string(res))

Output:

{"description":"Matcha Latte","sizes":[354,473,591],"styles":["iced","hot","extra hot"]}

Additional Information

To learn more about the operations discussed in this guide, see the following guides:

  • [Specify a Query](https://www.mongodb.com/docs/drivers/go/current/crud/query/query-document.md#std-label-golang-query-document

  • [Compound Operations](https://www.mongodb.com/docs/drivers/go/current/crud/compound-operations.md#std-label-golang-compound-operations

  • [Update Documents](https://www.mongodb.com/docs/drivers/go/current/crud/update.md#std-label-golang-change-document

  • Positional $ Operator

  • Positional $[] Operator

  • Positional $[\<identifier>] Operator

  • [Dot Notation](https://www.mongodb.com/docs/manual/core/document/#std-label-document-dot-notation

API Documentation

To learn more about any of the methods or types discussed in this guide, see the following API documentation:

  • [FindOneAndUpdate()](https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/mongo#Collection.FindOneAndUpdate

  • [FindOneAndUpdateOptionsBuilder.SetReturnDocument()](https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/mongo/options#FindOneAndUpdateOptionsBuilder.SetReturnDocument

  • [FindOneAndUpdateOptionsBuilder.SetArrayFilters()](https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/mongo/options#FindOneAndUpdateOptionsBuilder.SetArrayFilters

  • [UpdateMany()](https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/mongo#Collection.UpdateMany