对于 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 Server 8.0 或更高版本,则可以使用 MongoDB\Client::bulkWrite() 方法对同一集群中的多个集合和数据库执行批量写入操作。此方法在一次数据库调用中执行所有写入操作。要学习;了解有关此功能的更多信息,请参阅 Mongo.bulkWrite()MongoDB Server手册中的参考文档。

  • 集合:您可以使用 MongoDB\Collection::bulkWrite() 方法对单个集合执行批量写入操作。此方法对每种类型的写入操作进行一次数据库调用。示例,该方法可以在一次调用中执行多个更新操作,但会两次单独调用数据库以执行插入操作和替换操作。

本指南中的示例使用Atlas示例数据集中的 sample_restaurants.restaurantssample_mflix.movies 集合。要学习如何创建免费的MongoDB Atlas 集群并加载示例数据集,请参阅Atlas入门。

使用PHP库 v2.1 并连接到运行MongoDB Server 8.0 或更高版本的部署时,可以使用 MongoDB\Client::bulkWrite() 方法写入同一集群中的多个数据库和集合。此方法在一次调用中执行所有写入操作。

首先,使用 MongoDB\ClientBulkWrite 构建器创建 BulkWriteCommand 实例,以指定要执行的写入操作。以下代码演示了如何使用 createWithCollection() 方法从 MongoDB\Collection实例创建 ClientBulkWrite实例:

$restaurantCollection = $client->sample_restaurants->restaurants;
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);

然后,在 ClientBulkWrite实例上调用以下一个或多个写入方法以构造批量写入操作:

  • deleteOne()

  • deleteMany()

  • insertOne()

  • replaceOne()

  • updateOne()

  • updateMany()

要为后续写入操作选择不同的命名空间,请对 ClientBulkWrite实例调用 withCollection() 方法,如以下代码所示:

$movieCollection = $client->sample_mflix->movies;
$bulkWrite = $bulkWrite->withCollection($movieCollection);

以下部分介绍如何创建和使用 ClientBulkWrite 类来指定批量写入中的写入操作。执行批量操作部分演示了如何将 ClientBulkWrite对象传递给 bulkWrite() 方法以执行批量操作。

要指定插入操作,请在 ClientBulkWrite实例上调用 insertOne() 方法。

以下示例指定将文档插入到 sample_restaurants.restaurantssample_mflix.movies 集合中:

$restaurantCollection = $client->sample_restaurants->restaurants;
$movieCollection = $client->sample_mflix->movies;
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);
$bulkWrite->insertOne(['name' => 'Mongo Deli', 'cuisine' => 'Sandwiches']);
$bulkWrite = $bulkWrite->withCollection($movieCollection);
$bulkWrite->insertOne(['title' => 'The Green Ray', 'year' => 1986]);

要指定对第一个匹配文档执行更新操作,请对 ClientBulkWrite实例调用 updateOne() 方法。

以下示例指定对 sample_restaurants.restaurants集合中 name 值为 'Dandelion Bakery' 的第一个文档进行 $set更新:

$restaurantCollection = $client->sample_restaurants->restaurants;
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);
$bulkWrite->updateOne(
['name' => 'Dandelion Bakery'],
['$set' => ['grade' => 'B+']],
['upsert' => true],
);

要更新多个文档,请调用 updateMany() 方法。指定的操作会更新与查询过滤匹配的所有文档

以下示例指定对 sample_restaurants.restaurants集合中 name 值为 'Starbucks' 的所有匹配文档进行 $set更新:

$restaurantCollection = $client->sample_restaurants->restaurants;
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);
$bulkWrite->updateMany(
['name' => 'Starbucks'],
['$set' => ['cuisine' => 'Coffee (Chain)']],
);

要指定对第一个匹配文档执行替换操作,请对 ClientBulkWrite实例调用 replaceOne() 方法。

以下示例指定对 sample_restaurants.restaurants集合中 name 值为 'Dandelion Bakery' 的第一个文档执行替换操作:

$restaurantCollection = $client->sample_restaurants->restaurants;
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);
$bulkWrite->replaceOne(
['name' => 'Dandelion Bakery'],
['name' => 'Flower Patisserie', 'cuisine' => 'Bakery & Cafe'],
);

要指定对第一个匹配文档执行删除操作,请对 ClientBulkWrite实例调用 deleteOne() 方法。

以下示例指定删除 sample_restaurants.restaurants集合中第一个 borough 值为 'Queens' 的文档:

$restaurantCollection = $client->sample_restaurants->restaurants;
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);
$bulkWrite->deleteOne(
['borough' => 'Queens'],
);

要删除多个文档,请调用 deleteMany() 方法。指定的操作将删除与查询过滤匹配的所有文档

以下示例指定删除 sample_restaurants.restaurants集合中 name 值包含两个连续 'p' 字符的所有文档:

$restaurantCollection = $client->sample_restaurants->restaurants;
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);
$bulkWrite->deleteMany(
['name' => ['$regex' => 'p{2,}']],
);

构造 ClientBulkWrite实例来指定写入操作后,将其传递给 MongoDB\Client::bulkWrite() 方法。默认下,这些方法按照您在构造 ClientBulkWrite 时定义的顺序运行操作。

以下代码演示了如何使用 bulkWrite() 方法对多个命名空间执行批量写入操作:

$restaurantCollection = $client->sample_restaurants->restaurants;
$movieCollection = $client->sample_mflix->movies;
// Creates the bulk write command and sets the target namespace.
$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection($restaurantCollection);
// Specifies insertion of one document.
$bulkWrite->insertOne(['name' => 'Mongo Deli', 'cuisine' => 'Sandwiches']);
// Specifies a `$set` update to one document with the upsert option
// enabled.
$bulkWrite->updateOne(
['name' => 'Dandelion Bakery'],
['$set' => ['grade' => 'B+']],
['upsert' => true],
);
// Changes the target namespace.
$bulkWrite = $bulkWrite->withCollection($movieCollection);
// Specifies insertion of one document.
$bulkWrite->insertOne(['title' => 'The Green Ray', 'year' => 1986]);
// Specifies deletion of documents in which `title` has two consective
// 'd' characters.
$bulkWrite->deleteMany(
['title' => ['$regex' => 'd{2,}']],
);
// Specifies replacement of one document.
$bulkWrite->replaceOne(
['runtime' => ['$gte' => 200]],
['title' => 'Seven Samurai', 'runtime' => 203],
);
// Performs the bulk write operation.
$result = $client->bulkWrite($bulkWrite);
// Prints a summary of results.
echo 'Inserted documents: ', $result->getInsertedCount(), PHP_EOL;
echo 'Modified documents: ', $result->getModifiedCount(), PHP_EOL;
echo 'Deleted documents: ', $result->getDeletedCount(), PHP_EOL;
Inserted documents: 2
Modified documents: 2
Deleted documents: 200

您可以通过将大量传递给将选项值指定为参数的 ClientBulkWrite 构造函数来修改客户端批量写入操作的行为。下表描述了可在大量中设立的选项:

选项
说明

bypassDocumentValidation

指定操作是否绕过文档验证。这样,您就可以修改不符合模式验证要求的文档(如果存在)。有关模式验证的更多信息,请参阅MongoDB Server手册中的模式验证。默认值为
false

comment

为操作附加注释。 有关更多信息,请参阅MongoDB Server手册中的插入命令字段指南。

let

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

ordered

如果设立为true :当单个写入失败时,操作将停止,而不执行剩余的写入,并引发异常。如果设立为
false:当单个写入失败时,该操作会继续尝试剩余的写入操作(如有),然后引发异常。默认值为
true

verboseResults

指定是否返回详细结果。默认值为
false

以下示例创建一个 ClientBulkWrite实例并将 ordered 选项设置为 false

$bulkWrite = MongoDB\ClientBulkWrite::createWithCollection(
$restaurantCollection,
['ordered' => false],
);

注意

无序行为

无序批量操作不保证执行顺序。为了优化运行时间,顺序可以与您列出的方式不同。假设您在无序批量写入中指定以下写入操作:

$bulkWrite->insertOne(['_id' => 4045, 'title' => 'The Green Ray']);
$bulkWrite->deleteOne(['_id' => 4045]);

由于库可能会先运行任一操作,因此结果可能显示一个已删除的文档,也可能显示未删除任何文档。

您还可以在调用 bulkWrite() 方法时传递选项,指定用于操作的客户端端会话或写关注(write concern)。

MongoDB\Client::bulkWrite() 方法返回一个 MongoDB\BulkWriteCommandResult对象。该类包含以下方法:

方法
说明

getInsertedCount()

返回批量写入命令中所有插入操作插入的文档总数。

getMatchedCount()

返回批量写入命令中所有更新和替换操作匹配的文档总数。

getModifiedCount()

返回批量写入命令中所有更新和替换操作修改的文档总数。

getUpsertedCount()

返回批量写入命令中所有更新和替换操作更新或插入的文档总数。

getDeletedCount()

返回批量写入命令中所有删除操作删除的文档总数。

getInsertResults()

返回每个成功插入操作的结果映射。每个操作都由一个整数键表示,其中包含一个文档具有与该操作相对应的信息,例如插入的 _id 值。

getUpdateResults()

返回每个成功更新操作的结果映射。每个操作都由一个整数键表示,其中包含具有与该操作相对应的信息的文档。

getDeleteResults()

返回每个成功删除操作的结果映射。每个操作都由一个整数键表示,其中包含具有与该操作相对应的信息的文档。

isAcknowledged()

返回一个布尔值,指示服务器是否确认批量操作。

要运行批量写入操作,请将写入操作大量传递给 MongoDB\Collection::bulkWrite() 方法。使用以下语法指定写入操作:

[
[ 'deleteMany' => [ $filter ] ],
[ 'deleteOne' => [ $filter ] ],
[ 'insertOne' => [ $document ] ],
[ 'replaceOne' => [ $filter, $replacement, $options ] ],
[ 'updateMany' => [ $filter, $update, $options ] ],
[ 'updateOne' => [ $filter, $update, $options ] ],
]

提示

要学习;了解有关删除、插入、替换和更新操作的更多信息,请参阅增删改查操作。

调用 bulkWrite() 方法时,库会按照您在数组中指定的顺序自动运行写入操作。要学习;了解如何指示 bulkWrite() 以任意顺序运行写入操作,请参阅自定义批量写入操作。

此示例对restaurants集合运行以下写入操作:

  • 用于插入name值为'Mongo's Deli'的文档的插入操作

  • 用于更新name值为'Mongo's Deli'的文档的cuisine字段的更新操作

  • 删除操作,用于删除borough值为'Manhattan'的所有文档

$restaurantCollection = $client->sample_restaurants->restaurants;
$result = $restaurantCollection->bulkWrite(
[
[
'insertOne' => [
['name' => 'Mongo\'s Deli'],
['cuisine' => 'Sandwiches'],
['borough' => 'Manhattan'],
['restaurant_id' => '1234'],
],
],
[
'updateOne' => [
['name' => 'Mongo\'s Deli'],
['$set' => ['cuisine' => 'Sandwiches and Salads']],
],
],
[
'deleteMany' => [
['borough' => 'Manhattan'],
],
],
],
);

注意

当库运行批量操作时,它会使用目标集合的写关注(write concern)。无论执行顺序如何,驱动程序在尝试所有操作后都会报告所有写关注(write concern)错误。

您可以通过传递指定选项值的大量作为参数来修改MongoDB\Collection::bulkWrite()方法的行为。 下表描述了可在大量中设立的选项:

选项
说明

bypassDocumentValidation

指定操作是否绕过文档验证。这样,您就可以修改不符合模式验证要求的文档(如果存在)。有关模式验证的更多信息,请参阅MongoDB Server手册中的模式验证。默认值为
false

codec

设置用于编码或解码文档的编解码器。批量写入使用编解码器进行insertOne()replaceOne() 操作。有关更多信息,请参阅使用类型编解码器对数据进行编码。

writeConcern

设置操作的写关注(write concern)。 有关更多信息,请参阅MongoDB Server手册中的写关注。

let

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

ordered

如果设立为true :当单个写入失败时,操作将停止,而不执行剩余的写入,并引发异常。如果设立为
false:当单个写入失败时,该操作会继续尝试剩余的写入操作(如有),然后引发异常。默认值为
true

comment

为操作附加注释。 有关更多信息,请参阅MongoDB Server手册中的插入命令字段指南。

session

指定与操作关联的客户端会话。

以下示例调用bulkWrite()方法执行插入和删除操作,并将ordered选项设置为false

$result = $restaurantCollection->bulkWrite(
[
[
'insertOne' => [
['name' => 'Mongo\'s Pizza'],
['cuisine' => 'Italian'],
['borough' => 'Queens'],
['restaurant_id' => '5678'],
],
],
[
'deleteOne' => [
['restaurant_id' => '5678'],
],
],
],
['ordered' => false],
);

如果库先运行插入操作,则会删除一个文档。 如果它先运行删除操作,则不会删除任何文档。

注意

无序行为

无序批量操作不保证执行顺序。 为了优化运行时间,顺序可以与您列出的方式不同。

MongoDB\Collection::bulkWrite() 方法返回一个 MongoDB\BulkWriteResult对象。该类包含以下方法:

方法
说明

getInsertedCount()

返回批量写入命令中所有插入操作插入的文档总数。

getInsertedIds()

返回批量写入命令中所有插入操作插入的文档的 _id字段值的映射。

getMatchedCount()

返回批量写入命令中所有更新和替换操作匹配的文档总数。

getModifiedCount()

返回批量写入命令中所有更新和替换操作修改的文档总数。

getUpsertedCount()

返回批量写入命令中所有更新和替换操作更新或插入的文档总数。

getUpsertedIds()

返回批量写入命令中所有更新和替换操作更新或插入的文档的 _id字段值的映射。

getDeletedCount()

返回批量写入命令中所有删除操作删除的文档总数。

isAcknowledged()

返回一个布尔值,指示服务器是否确认批量操作。

要了解如何执行单个写入操作,请参阅以下指南:

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