Overview
在本指南中,您可以学习;了解如何使用批量写入操作在单个数据库调用中执行多个写入操作。
考虑这样一个场景:您要插入一个文档,更新多个其他文档,然后删除一个文档。 如果使用单独的方法,则每个操作都需要调用自己的数据库。
通过使用批量写入操作,您可以通过更少的数据库调用来执行多个写入操作。 您可以在以下级别执行批量写入操作:
客户端:如果您的应用程序连接到MongoDB Server 8.0 或更高版本,则可以使用
MongoDB\Client::bulkWrite()方法对同一集群中的多个集合和数据库执行批量写入操作。此方法在一次数据库调用中执行所有写入操作。要学习;了解有关此功能的更多信息,请参阅 Mongo.bulkWrite()MongoDB Server手册中的参考文档。集合:您可以使用
MongoDB\Collection::bulkWrite()方法对单个集合执行批量写入操作。此方法对每种类型的写入操作进行一次数据库调用。示例,该方法可以在一次调用中执行多个更新操作,但会两次单独调用数据库以执行插入操作和替换操作。
样本数据
本指南中的示例使用Atlas示例数据集中的 sample_restaurants.restaurants 和 sample_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.restaurants 和 sample_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 构造函数来修改客户端批量写入操作的行为。下表描述了可在大量中设立的选项:
选项 | 说明 |
|---|---|
| |
| |
| |
| 如果设立为 |
| 指定是否返回详细结果。默认值为 |
以下示例创建一个 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对象。该类包含以下方法:
方法 | 说明 |
|---|---|
| 返回批量写入命令中所有插入操作插入的文档总数。 |
| 返回批量写入命令中所有更新和替换操作匹配的文档总数。 |
| 返回批量写入命令中所有更新和替换操作修改的文档总数。 |
| 返回批量写入命令中所有更新和替换操作更新或插入的文档总数。 |
| 返回批量写入命令中所有删除操作删除的文档总数。 |
| 返回每个成功插入操作的结果映射。每个操作都由一个整数键表示,其中包含一个文档具有与该操作相对应的信息,例如插入的 |
| 返回每个成功更新操作的结果映射。每个操作都由一个整数键表示,其中包含具有与该操作相对应的信息的文档。 |
| 返回每个成功删除操作的结果映射。每个操作都由一个整数键表示,其中包含具有与该操作相对应的信息的文档。 |
| 返回一个布尔值,指示服务器是否确认批量操作。 |
集合批量写入
要运行批量写入操作,请将写入操作大量传递给 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()方法的行为。 下表描述了可在大量中设立的选项:
选项 | 说明 |
|---|---|
| |
| |
| |
| |
| 如果设立为 |
| |
| 指定与操作关联的客户端会话。 |
以下示例调用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对象。该类包含以下方法:
方法 | 说明 |
|---|---|
| 返回批量写入命令中所有插入操作插入的文档总数。 |
| 返回批量写入命令中所有插入操作插入的文档的 |
| 返回批量写入命令中所有更新和替换操作匹配的文档总数。 |
| 返回批量写入命令中所有更新和替换操作修改的文档总数。 |
| 返回批量写入命令中所有更新和替换操作更新或插入的文档总数。 |
| 返回批量写入命令中所有更新和替换操作更新或插入的文档的 |
| 返回批量写入命令中所有删除操作删除的文档总数。 |
| 返回一个布尔值,指示服务器是否确认批量操作。 |
更多信息
要了解如何执行单个写入操作,请参阅以下指南:
API 文档
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: