对于 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 Go驱动程序执行批量操作。批量操作通过在单个方法中执行多个写入操作来减少对服务器的调用次数。

CollectionClient 类均提供 BulkWrite() 方法。您可以使用 Collection.BulkWrite() 方法对单个集合执行多个写入操作。您可以使用 Client.BulkWrite() 方法跨多个命名空间执行批量写入。在MongoDB中,命名空间由数据库名称和集合名称组成。

重要

客户端批量写入服务器要求

要对 Client实例执行批量操作,请确保您的应用程序连接到MongoDB Server v8.0 或更高版本

本指南中的示例使用以下结构体:

  • Book 结构体,它对 db.books集合中的文档进行建模。每个文档都包含一本书的描述,其中包括标题、作者和页长。

  • Poem 结构体,它对 db.poems集合中的文档进行建模。每个文档都包含一首诗的描述,其中包括标题、作者和出版年份。

type Book struct {
Title string
Author string
Length int32
}
type Poem struct {
Title string
Author string
Year int32
}

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

bookColl := client.Database("db").Collection("books")
poemColl := client.Database("db").Collection("poems")
books := []any{
Book{Title: "My Brilliant Friend", Author: "Elena Ferrante", Length: 331},
Book{Title: "Lucy", Author: "Jamaica Kincaid", Length: 103},
}
poems := []any{
Poem{Title: "Song of Myself", Author: "Walt Whitman", Year: 1855},
Poem{Title: "The Raincoat", Author: "Ada Limon", Year: 2018},
}
bookInsert, err := bookColl.InsertMany(context.TODO(), books)
poemInsert, err := poemColl.InsertMany(context.TODO(), poems)

提示

不存在的数据库和集合

如果执行写操作时不存在必要的数据库和集合,服务器会隐式创建这些数据库和集合。

要对单个命名空间执行批量操作,请对集合调用 BulkWrite() 方法并将 WriteModel 文档大量作为参数传递。

要为一个命名空间上的批量操作定义写入操作,请为每个插入、替换、更新或删除创建一个 WriteModel

要为批量写入定义插入操作,请创建一个 InsertOneModel,指定要插入的文档。要插入多个文档,请为要插入的每个文档创建一个 InsertOneModel

您可以使用以下方法指定 InsertOneModel 的行为:

方法
说明

SetDocument()

要插入的文档。

以下示例创建了两个 InsertOneModel 实例,以将两个文档插入到 books集合中:

models := []mongo.WriteModel{
mongo.NewInsertOneModel().SetDocument(Book{Title: "Beloved", Author: "Toni Morrison", Length: 324}),
mongo.NewInsertOneModel().SetDocument(Book{Title: "Outline", Author: "Rachel Cusk", Length: 258}),
}

要为批量写入定义替换操作,请创建一个 ReplaceOneModel,指定要替换的文档和替换文档。要替换多个文档,请为每个要替换的文档创建一个 ReplaceOneModel

您可以使用以下方法指定 ReplaceOneModel 的行为:

方法
说明

SetCollation()

对结果进行排序时要使用的语言排序规则类型。

SetFilter()

查询筛选器,指定要替换的文档。

SetHint()

用于扫描文档的索引。

SetReplacement()

要替换匹配的文档的文档。

SetSort()

匹配文档的排序顺序。替换操作根据排序条件仅替换第一个文档。

SetUpsert()

如果查询筛选器不匹配任何文档,是否插入新文档。

以下示例创建一个 ReplaceOneModel 来替换 books集合中 title 值为 "Lucy" 的文档:

models := []mongo.WriteModel{
mongo.NewReplaceOneModel().SetFilter(bson.D{{"title", "Lucy"}}).
SetReplacement(Book{Title: "On Beauty", Author: "Zadie Smith", Length: 473}),
}

要定义批量写入的更新操作,请创建一个 UpdateOneModel,指定要更新的文档和一个更新文档。要更新多个文档,请使用 UpdateManyModel

您可以使用以下方法指定每个更新模型的行为:

方法
说明

SetArrayFilters()

更新应用到的数组元素。

SetCollation()

对结果进行排序时要使用的语言排序规则类型。

SetFilter()

查询筛选器,指定要更新的文档。

SetHint()

用于扫描文档的索引。

SetSort()

对匹配文档进行排序时使用的条件。此方法仅适用于 UpdateOneModel 类。

SetUpdate()

要应用到匹配文档的修改。

SetUpsert()

如果查询筛选器不匹配任何文档,是否插入新文档。

以下示例创建一个 UpdateOneModel 来更新books集合中的文档,如果 author"Elena Ferrante",则将文档的 length 递减 15

models := []mongo.WriteModel{
mongo.NewUpdateOneModel().SetFilter(bson.D{{"author", "Elena Ferrante"}}).
SetUpdate(bson.D{{"$inc", bson.D{{"length", -15}}}}),
}

要为批量写入定义删除操作,请创建 DeleteOneModel,指定要删除的文档。要删除多个文档,请使用 DeleteManyModel

您可以使用以下方法指定每个删除模型的行为:

方法
说明

SetCollation()

对结果进行排序时要使用的语言排序规则类型。

SetFilter()

查询筛选器,指定要删除的文档。

SetHint()

用于扫描文档的索引。

以下示例创建一个 DeleteManyModel 来删除books集合中 length 大于 300 的文档:

models := []mongo.WriteModel{
mongo.NewDeleteManyModel().SetFilter(bson.D{{"length", bson.D{{"$gt", 300}}}}),
}

要修改批量写入操作的行为,请将 BulkWriteOptions实例传递给 BulkWrite() 方法。

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

方法
说明

SetBypassDocumentValidation()

指定操作是否可以选择退出文档级验证。默认值:
false

SetComment()

指定要附加到操作的注释。默认值:
nil

SetLet()

指定包含值列表的文档,以提高操作的可读性。值必须是常量或不引用文档字段的闭合表达式。有关更多信息,请参阅MongoDB Server手册中删除和更新命令的 字段。默认值:let
nil

SetOrdered()

指定驾驶员在发生错误后是否停止执行写入操作。默认值:
true

BulkWrite() 方法返回 BulkWriteResult 类型,其中包括有关批量操作的信息。

BulkWriteResult 类型包含以下属性:

属性
说明

InsertedCount

插入的文档数量。

MatchedCount

在更新和替换操作中与查询筛选器匹配的文档数量。

ModifiedCount

通过更新和替换操作修改的文档数量。

DeletedCount

删除的文档数量。

UpsertedCount

通过更新和替换操作更新或插入的文档数量。

UpsertedIDs

操作索引到每个更新或插入文档的 _id 的映射。

Acknowledged

一个布尔值,表示写入操作是否已确认。

要指定批量写入是否按顺序执行操作,可以将 Ordered 选项设立为布尔值。要设立此选项,请指定 BulkWriteOptions实例的 Ordered字段。

默认下,BulkWrite() 方法会按照您添加的顺序运行批量操作,并在出现错误时停止。

提示

这相当于将 true 值传递给 SetOrdered() 方法,如以下代码所示:

opts := options.BulkWrite().SetOrdered(true)

要以任意顺序运行批量写入操作并在发生错误时继续,请将 false 值传递给 SetOrdered() 方法。该方法会在操作完成后报告错误。

以下示例按任意顺序执行以下动作:

  • 插入两个文档

  • title 为“My Brilliant Friend”的新文档替换为新文档

  • 如果当前 length 值小于 200,则将每个文档的 length10 递增

  • 删除 author字段值包含 "Jam" 的所有文档

models := []mongo.WriteModel{
mongo.NewInsertOneModel().SetDocument(Book{Title: "Middlemarch", Author: "George Eliot", Length: 904}),
mongo.NewInsertOneModel().SetDocument(Book{Title: "Pale Fire", Author: "Vladimir Nabokov", Length: 246}),
mongo.NewReplaceOneModel().SetFilter(bson.D{{"title", "My Brilliant Friend"}}).
SetReplacement(Book{Title: "Atonement", Author: "Ian McEwan", Length: 351}),
mongo.NewUpdateManyModel().SetFilter(bson.D{{"length", bson.D{{"$lt", 200}}}}).
SetUpdate(bson.D{{"$inc", bson.D{{"length", 10}}}}),
mongo.NewDeleteManyModel().SetFilter(bson.D{{"author", bson.D{{"$regex", "Jam"}}}}),
}
// Specifies that the bulk write is unordered
opts := options.BulkWrite().SetOrdered(false)
// Runs the bulk write operation and prints a summary of the
// data changes
results, err := bookColl.BulkWrite(context.TODO(), models, opts)
if err != nil {
panic(err)
}
fmt.Printf("Number of documents inserted: %d\n", results.InsertedCount)
fmt.Printf("Number of documents replaced or updated: %d\n", results.ModifiedCount)
fmt.Printf("Number of documents deleted: %d\n", results.DeletedCount)
Number of documents inserted: 2
Number of documents replaced or updated: 2
Number of documents deleted: 1

批量操作后,books(图书)集合中存在以下文档:

{"title":"Atonement","author":"Ian McEwan","length":351}
{"title":"Middlemarch","author":"George Eliot","length":904}
{"title":"Pale Fire","author":"Vladimir Nabokov","length":246}

注意

设置示例

此示例使用连接 URI 连接到MongoDB实例。要学习;了解有关连接到MongoDB实例的更多信息,请参阅创建 MongoClient。此示例还使用Atlas示例数据集包含的 sample_restaurants数据库中的 restaurants集合。您可以按照Atlas入门中的步骤将它们加载到MongoDB Atlas免费套餐上的数据库中。

以下示例是一个完全可运行的文件,它执行以下操作:

  • 匹配 name字段值为 "Towne Cafe" 的文档,并将其替换为 name字段值设立为 "New Towne Cafe"cuisine字段值设立为 "French" 的新文档

  • 匹配 name字段值为 Riviera Caterer 的文档,并将 name字段值更新为 "Riviera Cafe"

// Runs bulk write operations on a collection by using the Go driver
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/joho/godotenv"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
// Defines a Restaurant struct as a model for documents in the "restaurants" collection
type Restaurant struct {
Name string
RestaurantId string `bson:"restaurant_id,omitempty"`
Cuisine string `bson:"cuisine,omitempty"`
Address any `bson:"address,omitempty"`
Borough string `bson:"borough,omitempty"`
Grades []any `bson:"grades,omitempty"`
}
func main() {
if err := godotenv.Load(); err != nil {
log.Println("No .env file found")
}
var uri string
if uri = os.Getenv("MONGODB_URI"); uri == "" {
log.Fatal("You must set your 'MONGODB_URI' environment variable. See\n\t https://www.mongodb.com/zh-cn/docs/drivers/go/current/connect/mongoclient/#environment-variable")
}
client, err := mongo.Connect(options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}
defer func() {
if err = client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}()
coll := client.Database("sample_restaurants").Collection("restaurants")
// Creates write models that specify replace and update operations
models := []mongo.WriteModel{
mongo.NewReplaceOneModel().SetFilter(bson.D{{"name", "Towne Cafe"}}).
SetReplacement(Restaurant{Name: "New Towne Cafe", Cuisine: "French"}),
mongo.NewUpdateOneModel().SetFilter(bson.D{{"name", "Riviera Caterer"}}).
SetUpdate(bson.D{{"$set", bson.D{{"name", "Riviera Cafe"}}}}),
}
// Specifies that the bulk write is ordered
opts := options.BulkWrite().SetOrdered(true)
// Runs a bulk write operation for the specified write operations
results, err := coll.BulkWrite(context.TODO(), models, opts)
if err != nil {
panic(err)
}
// When you run this file for the first time, it should print output similar to the following:
// Number of documents replaced or modified: 2
fmt.Printf("Number of documents replaced or modified: %d", results.ModifiedCount)
}
Number of documents matched: 2
Number of documents modified: 2

要跨多个命名空间执行批量操作,请在客户端上调用 BulkWrite() 方法并将 ClientWriteModel 文档大量作为参数传递。

要为多个命名空间上的批量操作指定写入操作,请为每个 insert、replace、 更新或删除创建一个 ClientWriteModel。将每个写入模型传递给 ClientBulkWrite 结构并指定目标数据库和集合,如以下代码所示:

writes := []mongo.ClientBulkWrite{
{"<database name>", "<collection name>", <write model>},
...
}

要为批量写入定义插入操作,请创建 ClientInsertOneModel 以指定要插入的文档。要插入多个文档,请为要插入的每个文档创建一个 ClientInsertOneModel

您可以使用以下方法指定 ClientInsertOneModel 的行为:

方法
说明

SetDocument()

要插入的文档。

以下示例创建了两个 ClientInsertOneModel 实例,以将一个文档插入到 books集合中,并将一个文档插入到 poems集合中:

bookInsertDoc := Book{Title: "Parable of the Sower", Author: "Octavia E. Butler", Length: 320}
poemInsertDoc := Poem{Title: "Fame is a fickle food", Author: "Emily Dickinson", Year: 1659}
writes := []mongo.ClientBulkWrite{
{"db", "books", mongo.NewClientInsertOneModel().SetDocument(bookInsertDoc)},
{"db", "poems", mongo.NewClientInsertOneModel().SetDocument(poemInsertDoc)},
}

要为批量写入定义替换操作,请创建一个 ClientReplaceOneModel,指定要替换的文档和替换文档。要替换多个文档,请为每个要替换的文档创建一个 ClientReplaceOneModel

您可以使用以下方法指定 ClientReplaceOneModel 的行为:

方法
说明

SetCollation()

对结果进行排序时要使用的语言排序规则类型。

SetFilter()

查询筛选器,指定要替换的文档。

SetHint()

用于扫描文档的索引。

SetReplacement()

要替换匹配的文档的文档。

SetSort()

匹配文档的排序顺序。替换操作根据排序条件仅替换第一个文档。

SetUpsert()

如果查询筛选器不匹配任何文档,是否插入新文档。

此示例创建 ClientReplaceOneModel 实例来定义以下操作:

  • books集合执行替换操作,替换 title 值为 "Lucy" 的文档

  • poems集合执行替换操作,替换 title 值为 "Song of Myself" 的文档

writes := []mongo.ClientBulkWrite{
{"db", "books", mongo.NewClientReplaceOneModel().
SetFilter(bson.D{{"title", "Lucy"}}).
SetReplacement(Book{Title: "On Beauty", Author: "Zadie Smith", Length: 473})},
{"db", "poems", mongo.NewClientReplaceOneModel().
SetFilter(bson.D{{"title", "Song of Myself"}}).
SetReplacement(Poem{Title: "America", Author: "Walt Whitman", Year: 1888})},
}

要定义批量写入的更新操作,请创建一个 ClientUpdateOneModel,指定要更新的文档和一个更新文档。要更新多个文档,请使用 ClientUpdateManyModel

您可以使用以下方法指定每个更新模型的行为:

方法
说明

SetArrayFilters()

更新应用到的数组元素。

SetCollation()

对结果进行排序时要使用的语言排序规则类型。

SetFilter()

查询筛选器,指定要更新的文档。

SetHint()

用于扫描文档的索引。

SetSort()

对匹配文档进行排序时使用的条件。此方法仅适用于 ClientUpdateOneModel 类。

SetUpdate()

要应用到匹配文档的修改。

SetUpsert()

如果查询筛选器不匹配任何文档,是否插入新文档。

此示例创建 ClientUpdateOneModel 实例来定义以下操作:

  • books集合进行更新操作,以更新author 值为 "Elena Ferrante" 的文档

  • poems集合进行更新操作,以更新author 值为 "Ada Limon" 的文档

writes := []mongo.ClientBulkWrite{
{"db", "books", mongo.NewClientUpdateOneModel().
SetFilter(bson.D{{"author", "Elena Ferrante"}}).
SetUpdate(bson.D{{"$inc", bson.D{{"length", -15}}}})},
{"db", "poems", mongo.NewClientUpdateOneModel().
SetFilter(bson.D{{"author", "Ada Limon"}}).
SetUpdate(bson.D{{"author", "Ada Limón"}})},
}

注意

要更新与上示例中的 author字段查询筛选器匹配的所有文档,请使用 ClientUpdateManyModel 实例。

要为批量写入定义删除操作,请创建 ClientDeleteOneModel,指定要删除的文档。要删除多个文档,请使用 ClientDeleteManyModel

您可以使用以下方法指定每个删除模型的行为:

方法
说明

SetCollation()

对结果进行排序时要使用的语言排序规则类型。

SetFilter()

查询筛选器,指定要删除的文档。

SetHint()

用于扫描文档的索引。

此示例创建 ClientDeleteOneModel 实例来定义以下操作:

  • books集合执行删除操作,删除length 值为 103 的文档

  • poems集合执行删除操作,删除year 值为 1855 的文档

writes := []mongo.ClientBulkWrite{
{"db", "books", mongo.NewClientDeleteOneModel().
SetFilter(bson.D{{"length", 103}})},
{"db", "poems", mongo.NewClientDeleteOneModel().
SetFilter(bson.D{{"year", 1855}})},
}

要修改批量写入操作的行为,请将 ClientBulkWriteOptions实例传递给 BulkWrite() 方法。

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

方法
说明

SetBypassDocumentValidation()

指定操作是否可以选择退出文档级验证。默认值:
false

SetOrdered()

指定驾驶员在发生错误后是否停止执行写入操作。默认值:
true

SetComment()

指定要附加到操作的注释。默认值:
nil

SetLet()

指定包含值列表的文档,以提高操作的可读性。值必须是常量或不引用文档字段的闭合表达式。有关更多信息,请参阅MongoDB Server手册中删除和更新命令的 字段。默认值:let
nil

SetWriteConcern()

指定操作的写关注(write concern)。默认值:
nil

SetVerboseResults()

指定结果中是否包含每个成功操作的详细信息。默认值:
false

BulkWrite() 方法返回 ClientBulkWriteResult 类型,其中包括有关批量操作的信息。

ClientBulkWriteResult 类型包含以下属性:

属性
说明

InsertedCount

插入的文档数量。

MatchedCount

在更新和替换操作中与查询筛选器匹配的文档数量。

ModifiedCount

通过更新和替换操作修改的文档数量。

DeletedCount

删除的文档数量。

UpsertedCount

通过更新和替换操作更新或插入的文档数量。

InsertResults

操作索引到每个插入文档的 _id 值的映射。

UpdateResults

操作索引到每个更新文档的 _id 值的映射。

DeleteResults

操作索引到每个已删除文档的 _id 值的映射。

Acknowledged

一个布尔值,表示写入操作是否已确认。

HasVerboseResults

布尔值,表示结果是否包含详细结果。

要指定批量写入是否按顺序执行操作,可以将 Ordered 选项设立为布尔值。要设立此选项,请指定 ClientBulkWriteOptions实例的 Ordered字段。

默认情况下,BulkWrite() 方法按照您添加的顺序执行批量操作,并在出现错误时停止执行。

提示

这相当于将 true 值传递给 SetOrdered() 方法,如以下代码所示:

opts := options.ClientBulkWrite().SetOrdered(true)

要以任意顺序运行批量写入操作并在发生错误时继续,请将 false 值传递给 SetOrdered() 方法。该方法会在操作完成后报告错误。

以下示例按任意顺序执行以下动作:

  • 将新文档插入到 bookspoems 集合中

  • 更新 poems集合中 title 值为 "The Raincoat" 的文档

  • 替换 books集合中 title 值为 "My Brilliant Friend" 的文档

writes := []mongo.ClientBulkWrite{
{"db", "books", mongo.NewClientInsertOneModel().
SetDocument(Book{Title: "Middlemarch", Author: "George Eliot", Length: 904})},
{"db", "poems", mongo.NewClientInsertOneModel().
SetDocument(Poem{Title: "Mad Girl's Love Song", Author: "Sylvia Plath", Year: 1953})},
{"db", "poems", mongo.NewClientUpdateOneModel().
SetFilter(bson.D{{"title", "The Raincoat"}}).
SetUpdate(bson.D{{"title", "The Conditional"}})},
{"db", "books", mongo.NewClientReplaceOneModel().
SetFilter(bson.D{{"title", "My Brilliant Friend"}}).
SetReplacement(Book{Title: "The Story of a New Name", Author: "Elena Ferrante", Length: 480})},
}
opts := options.ClientBulkWrite().SetOrdered(false)
results, err := client.BulkWrite(context.TODO(), writes, opts)
if err != nil {
panic(err)
}
fmt.Printf("Number of documents inserted: %d\n", results.InsertedCount)
fmt.Printf("Number of documents replaced or updated: %d\n", results.ModifiedCount)
Number of documents inserted: 2
Number of documents replaced or updated: 2

要了解有关执行上述操作的更多信息,请参阅以下指南:

要详细学习;了解用于集合批量写入的方法或类型,请参阅以下API文档:

要详细学习;了解用于客户端端批量写入的方法或类型,请参阅以下API文档: