复合操作
概述
在本指南中,您可以学习如何执行复合操作。
复合操作将读取和写入操作合并为单个操作。如果您单独执行读取和写入操作,则可能在两者之间有人修改文档。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)
每个文档都包含一个大学课程的描述,包括课程标题和最大入学人数,分别对应每个文档中的title
和enrollment
字段。
提示
不存在的数据库和集合
如果您在执行写入操作时所需的数据库和集合不存在,则服务器会隐式创建它们。
查找并删除
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 文档
要了解更多关于本指南中讨论的任何方法或类型的信息,请参阅以下 API 文档