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

复合操作

本页内容

  • 概述
  • 查找并删除
  • 查找并更新
  • 查找并替换
  • 附加信息

在本指南中,您可以学习如何执行复合操作

复合操作将读取和写入操作合并为单个操作。如果您单独执行读取和写入操作,则可能在两者之间有人修改文档。MongoDB通过在复合操作期间对您正在修改的文档执行写入锁来防止这种情况。

MongoDB支持以下复合操作

  • 查找并删除一个文档

  • 查找并更新一个文档

  • 查找并替换一个文档

提示

要了解如何同时执行多个文档的复合操作,请参阅事务指南。

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

type Course struct {
Title string
Enrollment int32
}

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

coll := client.Database("db").Collection("courses")
docs := []interface{}{
Course{Title: "Representation Theory", Enrollment: 40},
Course{Title: "Early Modern Philosophy", Enrollment: 25},
Course{Title: "Animal Communication", Enrollment: 18},
}
result, err := coll.InsertMany(context.TODO(), docs)

每个文档都包含一个大学课程的描述,包括课程标题和最大入学人数,分别对应每个文档中的titleenrollment字段。

提示

不存在的数据库和集合

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

FindOneAndDelete() 方法查找与指定查询过滤器匹配的第一个文档并将其删除。该方法返回一个包含被删除文档的 SingleResult

注意

FindOneAndDelete() 方法是一个原子操作,这意味着它防止任何其他写操作在它完成之前更改匹配的文档。deleteOne() 方法也是一个原子操作,但它与 FindOneAndDelete() 不同,因为在匹配的文档中您不能指定排序顺序。

要单独进行查找和删除操作,请调用
findOne() 方法后跟 deleteOne() 方法。

您可以通过传递一个 FineOneAndDeleteOptions 来修改 FindOneAndDelete() 方法的行为。如果您没有指定 FineOneAndDeleteOptions,驱动程序将使用每个选项的默认值。

FineOneAndDeleteOptions 类型允许您使用以下方法配置选项

方法
描述
SetCollation()
排序结果时使用的语言排序类型。
默认值:nil
SetMaxTime()
查询在服务器上运行的最大时间。
默认值:nil
SetProjection()
要包含在返回的文档中的字段。
默认值:nil
SetSort()
排序字段和排序方向以对匹配的文档进行排序。
默认值:nil
SetHint()
用于扫描文档的索引。
默认值:nil

以下示例使用FindOneAndDelete()方法来匹配并删除第一个enrollment字段值小于20的文档

filter := bson.D{{"enrollment", bson.D{{"$lt", 20}}}}
var deletedDoc Course
err := coll.FindOneAndDelete(context.TODO(), filter).Decode(&deletedDoc)
if err != nil {
panic(err)
}
res, _ := bson.MarshalExtJSON(deletedDoc, false, false)
fmt.Println(string(res))
{"title":"Animal Communication","enrollment":18}

FindOneAndUpdate()方法查找第一个与指定查询过滤器匹配的文档,并根据更新文档进行更新。该方法返回一个包含匹配文档的SingleResult

注意

FindOneAndUpdate()方法是一个原子操作,这意味着它防止其他任何写操作在完成之前更改匹配的文档。《updateOne()`方法也是一个原子操作,但它与《FindOneAndUpdate()`不同,您不能为匹配的文档指定排序顺序。

要单独进行查找和更新操作,请先调用《findOne()`方法,然后调用《updateOne()`方法。

您可以通过传入一个 FindOneAndUpdateOptions 来修改 FindOneAndUpdate() 方法的行怍。如果您没有指定 FindOneAndUpdateOptions,驱动程序将使用每个选项的默认值。

FindOneAndUpdateOptions 类型允许您使用以下方法配置选项

方法
描述
SetArrayFilters()
更新应用的数组元素。
默认值:nil
SetBypassDocumentValidation()
是否允许写操作绕过文档级别验证
默认:false
SetCollation()
排序结果时使用的语言排序类型。
默认值:nil
SetMaxTime()
查询在服务器上运行的最大时间。
默认值:nil
SetProjection()
要包含在返回的文档中的字段。
默认值:nil
SetReturnDocument()
是否在 SingleResult 中返回原始或更新后的文档。
默认:options.Before
SetSort()
排序字段和排序方向以对匹配的文档进行排序。
默认值:nil
SetUpsert()
是否在查询过滤器没有匹配任何文档时插入新文档。
默认:false
SetHint()
用于扫描文档的索引。
默认值:nil

以下示例使用 FindOneAndUpdate() 方法依次执行以下操作

  • 匹配第一个标题字段值包含 "Modern" 的文档

  • 将匹配的文档的 enrollment 字段值更新为 32

  • 返回更新后的文档

filter := bson.D{{"title", bson.D{{"$regex", "Modern"}}}}
update := bson.D{{"$set", bson.D{{"enrollment", 32}}}}
opts := options.FindOneAndUpdate().SetReturnDocument(options.After)
var updatedDoc Course
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))
{"title":"Early Modern Philosophy","enrollment":32}

FindOneAndReplace() 方法查找第一个匹配指定查询过滤器的文档,并用替换文档替换它。该方法返回一个包含匹配文档的 SingleResult

注意

此方法与 ReplaceOne() 方法不同。FindOneAndReplace() 将查找和替换作为一个单一操作执行,并消除了在两个操作之间有人更改文档的可能性。

您可以通过传入一个 FindOneAndReplaceOptions 来修改 FindOneAndReplace() 方法的行为。如果您没有指定 FindOneAndReplaceOptions,驱动程序将使用每个选项的默认值。

FindOneAndReplaceOptions 类型允许您使用以下方法配置选项

方法
描述
SetBypassDocumentValidation()
是否允许写操作绕过文档级别验证
默认:false
SetCollation()
排序结果时使用的语言排序类型。
默认值:nil
SetMaxTime()
查询在服务器上运行的最大时间。
默认值:nil
SetProjection()
要包含在返回的文档中的字段。
默认值:nil
SetReturnDocument()
SingleResult 中是否返回原始文档或替换后的文档。
默认值:nil
SetSort()
排序字段和排序方向以对匹配的文档进行排序。
默认值:nil
SetUpsert()
是否在查询过滤器没有匹配任何文档时插入新文档。
默认:false
SetHint()
用于扫描文档的索引。
默认值:nil

以下示例使用 FindOneAndReplace() 方法按以下顺序执行以下操作

  • 匹配第一个标题为 "Representation Theory" 的文档

  • 将匹配的文档替换为一个新的文档,其中标题为 "Combinatorial Theory",注册人数为 35

filter := bson.D{{"title", "Representation Theory"}}
replacement := Course{Title: "Combinatorial Theory", Enrollment: 35}
var outdatedDoc Course
err := coll.FindOneAndReplace(context.TODO(), filter, replacement).Decode(&previousDoc)
if err != nil {
panic(err)
}
res, _ := bson.MarshalExtJSON(outdatedDoc, false, false)
fmt.Println(string(res))
{"title":"Representation Theory","enrollment":40}

有关执行所提操作的更多信息,请参阅以下指南

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

返回

批量操作