文档菜单
文档首页
/ / /
Go 驱动
/ / /

更新文档中的数组

本页内容

  • 概述
  • 示例数据
  • 指定数组元素
  • 第一个数组元素
  • 多个数组元素
  • 所有数组元素
  • 附加信息
  • API 文档

在本指南中,您可以学习如何在单个或多个文档中更新数组元素。

要更新数组中的元素,请执行以下操作

  • 提供更新文档,指定更新内容。

  • 指定要更新的数组元素。

  • 使用具有这些规范的更新操作执行更新。

本指南中的示例使用以下Drink 结构体作为 drinks 集合中文档的模型

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

The truncate struct tag 允许驱动程序在反序列化时将类型如 float64 截断为 int32

要运行本指南中的示例,使用以下代码片段将示例数据加载到 db.drinks 集合中

coll := client.Database("db").Collection("drinks")
docs := []interface{}{
Drink{Description: "Matcha Latte", Sizes: []int32{12, 16, 20}, Styles: []string{"iced", "hot", "extra hot"}},
}
result, err := coll.InsertMany(context.TODO(), docs)

每份文档都包含对一种饮料的描述,包括饮料的描述、可用盎司大小和可用制备风格,分别对应文档中的descriptionsizesstyles字段。

提示

不存在的数据库和集合

当您执行写操作时,如果所需的数据库和集合不存在,服务器将隐式创建它们。

以下示例使用FindOneAndUpdate()方法检索和更新文档,并返回更新发生后的文档状态。如果您想更新具有数组字段的多个文档,请使用UpdateMany()方法。

要指定要更新的数组元素,请使用位置运算符。位置运算符可以指定要更新的第一个多个所有数组元素。

要使用位置运算符指定数组元素,请使用点表示法。点表示法是用于导航数组元素和嵌套文档字段的属性访问语法。

要更新与查询筛选器匹配的第一个数组元素,请使用位置$运算符。查询筛选器必须针对数组字段。

本示例执行以下操作

  • sizes 数组中匹配值小于或等于 16 的元素。

  • 将匹配到的第一个数组值减少 2

filter := bson.D{{"sizes", bson.D{{"$lte", 16}}}}
update := bson.D{{"$inc", bson.D{{"sizes.$", -2}}}}
opts := options.FindOneAndUpdate().
SetReturnDocument(options.After)
var updatedDoc Drink
err := coll.FindOneAndUpdate(context.TODO(), filter, update, opts).Decode(&updatedDoc)
if err != nil {
panic(err)
}
res, _ := bson.MarshalExtJSON(updatedDoc, false, false)
fmt.Println(string(res))
{"description":"Matcha Latte","sizes":[10,16,20],"styles":["iced","hot","extra hot"]}

注意

查询过滤器匹配值 1216。由于操作首先匹配 12,因此它被减少。如果您想更新两个匹配值,请参阅多个数组元素。

要更新与您的查询过滤器匹配的多个数组元素,请使用带标识符的过滤位置 $[<identifier>] 操作符。您必须在更新操作中包含数组过滤器,以指定要更新的数组元素。

<identifier> 是您在数组过滤器中使用的名称。此值必须以小写字母开头,并且只能包含字母数字字符。

本示例执行以下操作

  • 创建一个名为 hotOptions 的标识符,以匹配包含 "hot" 的数组元素。

  • 使用 SetArrayFilters() 方法应用数组过滤器。

  • 删除这些数组元素。

identifier := []interface{}{bson.D{{"hotOptions", bson.D{{"$regex", "hot"}}}}}
update := bson.D{{"$unset", bson.D{{"styles.$[hotOptions]", ""}}}}
opts := options.FindOneAndUpdate().
SetArrayFilters(options.ArrayFilters{Filters: identifier}).
SetReturnDocument(options.After)
var updatedDoc Drink
err := coll.FindOneAndUpdate(context.TODO(), bson.D{}, update, opts).Decode(&updatedDoc)
if err != nil {
panic(err)
}
res, _ := bson.MarshalExtJSON(updatedDoc, false, false)
fmt.Println(string(res))
{"description":"Matcha Latte","sizes":[12,16,20],"styles":["iced","",""]}

要更新所有数组元素,请使用所有位置 $[] 操作符。

注意

如果您为数组字段指定了查询过滤器,位置 $[] 操作符将忽略查询过滤器并更新所有数组元素。

此示例将 sizes 数组中的每个元素乘以 29.57,以将盎司转换为毫升。

update := bson.D{{"$mul", bson.D{{"sizes.$[]", 29.57}}}}
opts := options.FindOneAndUpdate().
SetReturnDocument(options.After)
var updatedDoc Drink
err := coll.FindOneAndUpdate(context.TODO(), bson.D{}, update, opts).Decode(&updatedDoc)
if err != nil {
panic(err)
}
res, _ := bson.MarshalExtJSON(updatedDoc, false, false)
fmt.Println(string(res))
{"description":"Matcha Latte","sizes":[354,473,591],"styles":["iced","hot","extra hot"]}

要了解更多关于本指南中讨论的操作的信息,请参阅以下指南

要了解本指南中讨论的任何方法或类型,请参阅以下 API 文档

返回

修改