对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
MongoDB Branding Shape
Click here >
Docs 菜单

复合运算符

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

复合操作会将读取和写入操作组合为单个操作。如果您分别执行读取和写入操作,那么其他人可能会在这两个操作之间更改文档。MongoDB 通过在复合操作期间对您正在修改的文档放置写锁来防止这种情况。

MongoDB 支持以下复合操作:

提示

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

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

type Course struct {
Title string
Enrollment int32
}

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

coll := client.Database("db").Collection("courses")
docs := []any{
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() 方法。

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

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

方法
说明

SetCollation()

对结果进行排序时使用的语言排序规则类型。默认值:
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() 不同,因为使用 UpdateOne() 时无法返回已更新文档的前像。

要查找文档并在单独的操作中更新文档,请调用 FindOne() 方法,然后调用 UpdateOne() 方法。

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

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

方法
说明

SetArrayFilters()


更新应用到的大量元素。默认值:nil

SetBypassDocumentValidation()

是否允许写入操作选择退出文档级验证。默认值:
false

SetCollation()

对结果进行排序时使用的语言排序规则类型。默认值:
nil

SetProjection()


要包含在返回的文档中的字段。默认值:nil

SetReturnDocument()

是否在 中返回原始文档或更新后的文档。默认值:SingleResult
options.Before

SetSort()

对匹配的文档进行排序的排序字段和方向。默认值:
nil

SetUpsert()

如果查询过滤与任何文档都不匹配,是否插入新文档。默认值:
false

SetHint()

用于扫描文档的索引。默认值:
nil

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

  • 匹配title字段值包含“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

SetProjection()


要包含在返回的文档中的字段。默认值:nil

SetReturnDocument()

是否在 中返回原始文档或替换后的文档。默认值:SingleResult
nil

SetSort()

对匹配的文档进行排序的排序字段和方向。默认值:
nil

SetUpsert()

如果查询过滤与任何文档都不匹配,是否插入新文档。默认值:
false

SetHint()

用于扫描文档的索引。默认值:
nil

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

  • 匹配title为“Representation Theory”的第一个文档

  • 用新文档替换匹配的文档,其中 title 是“组合理论”,enrollment35

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 文档: