Overview
在本指南中,您可以了解如何使用 Node.js 驱动程序执行批量操作。批量操作有助于减少对服务器的调用次数。您可以在一次执行多个操作,而不是为每个操作发送请求。
提示
要学习;了解有关批量操作的更多信息,请参阅MongoDB Server手册中的批量写入操作。
您可以使用批量操作对集合执行多个写入操作。您还可以从客户端运行批量操作,这样就可以跨多个命名空间执行批量写入。在MongoDB中,命名空间由数据库名称和集合名称组成,格式为 <database>.<collection>。
注意
驱动程序可以处理的写入操作数量没有限制。驱动程序根据maxWriteBatchSize(为 100,000,且无法修改)将数据批处理。如果该批处理包含超过 100、000 个操作,则驱动程序会将该批处理分成多个较小的组,且其计数小于或等于 maxWriteBatchSize。示例,如果操作包含 250,000 操作,则驱动程序会创建三个批处理:两个包含 100,000 操作,一个包含 50,000 操作。
本指南包括以下部分:
批量插入操作描述了如何在集合或客户端上执行批量插入操作。
批量替换操作描述了如何在集合或客户端上执行批量替换操作。
批量更新操作描述了如何在集合或客户端上执行批量更新操作。
批量删除操作描述了如何在集合或客户端上执行批量删除操作。
其他信息提供了指向本指南中提及的类型和方法的资源和API文档的链接。
重要
服务器和驱动程序版本要求
集合级批量写入操作需要以下版本:
MongoDB Server 3.2 或更高版本
Node.js驱动程序版本 3.6 或更高版本
客户端级批量写入操作需要以下版本:
MongoDB Server 8.0 或更高版本
Node.js驱动程序版本 6.10 或更高版本
样本数据
The examples in this guide use the movies and users collections in the sample_mflix database, which is included in the Atlas sample datasets. To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see the MongoDB Get Started guide.
批量插入操作
要执行批量插入操作,请为要插入的每个文档创建批量操作模型。然后,将这些模型的列表传递给 bulkWrite() 方法。
本节介绍如何执行以下类型的批量操作:
集合批量插入
要对集合执行批量插入操作,请为每个操作创建一个 InsertOneModel。然后,对集合调用 bulkWrite() 方法,并将模型大量作为参数传递。要创建 InsertOneModel,请指定模型的 document字段并将其设立为要插入的文档。
例子
此示例将执行以下动作:
在大量中指定两个
InsertOneModel实例。每个InsertOneModel代表一个要插入到sample_mflix数据库的movies集合中的文档。在
movies集合上调用bulkWrite()方法,并将模型大量作为参数传递。打印插入文档的数量。
const insertModels = [{ insertOne: { document: { title: "The Favourite", year: 2018, rated: "R", released: "2018-12-21" } }}, { insertOne: { document: { title: "I, Tonya", year: 2017, rated: "R", released: "2017-12-08" } }}];
const insertResult = await movies.bulkWrite(insertModels);console.log(`Inserted documents: ${insertResult.insertedCount}`);客户端批量插入
要跨多个集合或数据库执行批量插入操作,请为每个操作创建一个 ClientBulkWriteModel。然后,在客户端上调用 bulkWrite() 方法并将模型大量作为参数传递。
下表描述了您可以在 ClientBulkWriteModel 中设立以指定插入操作的字段:
字段 | 说明 |
|---|---|
| 要在其中插入文档的命名空间空间。 |
| 要执行的操作。对于插入操作,请将此字段设立为 |
| 要插入的文档。 |
例子
此示例将执行以下动作:
在一个大量中指定三个
ClientBulkWriteModel实例。前两个模型表示要插入到movies集合中的文档,最后一个模型表示要插入到users集合中的文档。在客户端上调用
bulkWrite()方法,并将模型大量作为参数传递。打印插入文档的数量。
const clientInserts = [{ namespace: "sample_mflix.movies", name: "insertOne", document: { title: "The Favourite", year: 2018, rated: "R", released: "2018-12-21" }}, { namespace: "sample_mflix.movies", name: "insertOne", document: { title: "I, Tonya", year: 2017, rated: "R", released: "2017-12-08" }}, { namespace: "sample_mflix.users", name: "insertOne", document: { name: "Brian Schwartz", email: "bschwartz@example.com" }}];
const clientInsertRes = await client.bulkWrite(clientInserts);console.log(`Inserted documents: ${clientInsertRes.insertedCount}`);批量替换操作
要执行批量替换操作,请为要替换的每个文档创建批量操作模型。然后,将这些模型的列表传递给 bulkWrite() 方法。
本节介绍如何执行以下类型的批量操作:
集合批量替换
要对集合执行批量替换操作,请为每个操作创建一个 ReplaceOneModel。然后,对集合调用 bulkWrite() 方法,并将模型大量作为参数传递。
下表描述了您可以在 ReplaceOneModel 中设立的字段:
字段 | 说明 |
|---|---|
| 与要替换的文档匹配的过滤器。 |
| 替换文档。 |
| (可选)对结果进行排序时使用的排序规则。要学习有关排序规则的更多信息,请参阅 排序规则部分的配置 CRUD 操作指南。 |
| (可选)用于操作的索引。要学习;了解有关索引的更多信息,请参阅 用于查询优化的索引 指南。 |
| (可选)如果没有文档与过滤器匹配,是否创建新文档。 |
例子
此示例将执行以下动作:
在大量中指定两个
ReplaceOneModel实例。ReplaceOneModel实例包含替换movies集合中表示电影的文档的指令。在
movies集合上调用bulkWrite()方法,并将模型大量作为参数传递。打印已修改文档的数量。
const replaceOperations = [{ replaceOne: { filter: { title: "The Dark Knight" }, replacement: { title: "The Dark Knight Rises", year: 2012, rating: "PG-13" }, upsert: false }}, { replaceOne: { filter: { title: "Inception" }, replacement: { title: "Inception Reloaded", year: 2010, rating: "PG-13" }, upsert: false }}];
const replaceResult = await movies.bulkWrite(replaceOperations);console.log(`Modified documents: ${replaceResult.modifiedCount}`);客户端批量替换
要跨多个集合或数据库执行批量替换操作,请为每个操作创建一个 ClientBulkWriteModel。然后,在客户端上调用 bulkWrite() 方法并将模型大量作为参数传递。
下表描述了您可以在 ClientBulkWriteModel 中设立以指定替换操作的字段:
字段 | 说明 |
|---|---|
| 要替换文档的命名空间空间。 |
| 要执行的操作。对于替换操作,请将此字段设立为 |
| 与要替换的文档匹配的过滤器。 |
| 替换文档。 |
| (可选)对结果进行排序时使用的排序规则。要学习有关排序规则的更多信息,请参阅 排序规则部分的配置 CRUD 操作指南。 |
| (可选)用于操作的索引。要学习;了解有关索引的更多信息,请参阅 用于查询优化的索引 指南。 |
例子
此示例将执行以下动作:
在一个大量中指定三个
ClientBulkWriteModel实例。前两个模型包含movies集合中文档的替换指令,最后一个模型包含users集合中文档的替换指令。在客户端上调用
bulkWrite()方法,并将模型大量作为参数传递。打印已修改文档的数量。
const clientReplacements = [{ namespace: "sample_mflix.movies", name: "replaceOne", filter: { title: "The Dark Knight" }, replacement: { title: "The Dark Knight Rises", year: 2012, rating: "PG-13" }}, { namespace: "sample_mflix.movies", name: "replaceOne", filter: { title: "Inception" }, replacement: { title: "Inception Reloaded", year: 2010, rating: "PG-13" }}, { namespace: "sample_mflix.users", name: "replaceOne", filter: { name: "April Cole" }, replacement: { name: "April Franklin", email: "aprilfrank@example.com" }}];
const clientReplaceRes = await client.bulkWrite(clientReplacements);console.log(`Modified documents: ${clientReplaceRes.modifiedCount}`);批量更新操作
要执行批量更新操作,请为要进行的每个更新创建批量操作模型。然后,将这些模型的列表传递给 bulkWrite() 方法。
本节介绍如何执行以下类型的批量操作:
集合批量更新
要对集合执行批量更新操作,请为每个操作创建一个 UpdateOneModel 或 UpdateManyModel。然后,对集合调用 bulkWrite() 方法,并将模型大量作为参数传递。UpdateOneModel 仅更新与过滤匹配的一个文档,而 UpdateManyModel 会更新与过滤匹配的所有文档。
下表描述了您可以在 UpdateOneModel 或 UpdateManyModel 中设立的字段:
字段 | 说明 |
|---|---|
| 与要更新的一个或多个文档相匹配的过滤器。在 |
| 要执行的更新。 |
| (可选)一设立过滤器,用于指定在更新数组值字段时要对哪些数组元素进行更新。 |
| (可选)对结果进行排序时使用的排序规则。要学习有关排序规则的更多信息,请参阅 排序规则部分的配置 CRUD 操作指南。 |
| (可选)用于操作的索引。要学习;了解有关索引的更多信息,请参阅 用于查询优化的索引 指南。 |
| (可选)如果没有文档与过滤器匹配,是否创建新文档。默认下,此字段设立为 |
例子
此示例将执行以下动作:
在大量中指定一个
UpdateOneModel和一个UpdateManyModel实例。 这些模型包含更新表示movies集合中的电影的文档的指令。在
movies集合上调用bulkWrite()方法,并将模型大量作为参数传递。打印已修改文档的数量。
const updateOperations = [{ updateOne: { filter: { title: "Interstellar" }, update: { $set: { title: "Interstellar Updated", genre: "Sci-Fi Adventure" } }, upsert: true }}, { updateMany: { filter: { rated: "PG-13" }, update: { $set: { rated: "PG-13 Updated", genre: "Updated Genre" } } }}];
const updateResult = await movies.bulkWrite(updateOperations);console.log(`Modified documents: ${updateResult.modifiedCount}`);客户端批量更新
要跨多个集合或数据库执行批量更新操作,请为每个操作创建一个 ClientBulkWriteModel。然后,在客户端上调用 bulkWrite() 方法并将模型大量作为参数传递。
下表描述了您可以在 ClientBulkWriteModel 中设立以指定更新操作的字段:
字段 | 说明 |
|---|---|
| 要在其中更新文档的命名空间。 |
| 要执行的操作。对于更新操作,请将此字段设立为 |
| 与要更新的一个或多个文档相匹配的过滤器。如果将模型 |
| 要执行的更新。 |
| (可选)一设立过滤器,用于指定在更新数组值字段时要对哪些数组元素进行更新。 |
| (可选)对结果进行排序时使用的排序规则。要学习有关排序规则的更多信息,请参阅 排序规则部分的配置 CRUD 操作指南。 |
| (可选)用于操作的索引。要学习;了解有关索引的更多信息,请参阅 用于查询优化的索引 指南。 |
| (可选)如果没有文档与过滤器匹配,是否创建新文档。默认下,此字段设立为 |
例子
此示例将执行以下动作:
在大量中指定两个
ClientBulkWriteModel实例。第一个模型指定对movies集合进行多次更新操作,第二个模型指定对users集合进行一次更新操作。在客户端上调用
bulkWrite()方法,并将模型大量作为参数传递。打印已修改文档的数量。
const clientUpdates = [{ namespace: "sample_mflix.movies", name: "updateMany", filter: { rated: "PG-13" }, update: { $set: { rated: "PG-13 Updated", genre: "Updated Genre" } }, upsert: false}, { namespace: "sample_mflix.users", name: "updateOne", filter: { name: "Jon Snow" }, update: { $set: { name: "Aegon Targaryen", email: "targaryen@example.com" } }, upsert: false}];const clientUpdateRes = await client.bulkWrite(clientUpdates);console.log(`Modified documents: ${clientUpdateRes.modifiedCount}`);批量删除操作
要执行批量删除操作,请为每个删除操作创建批量操作模型。然后,将这些模型的列表传递给 bulkWrite() 方法。
本节介绍如何执行以下类型的批量操作:
集合批量删除
要对集合执行批量删除操作,请为每个操作创建一个 DeleteOneModel 或 DeleteManyModel。然后,对集合调用 bulkWrite() 方法,并将模型大量作为参数传递。DeleteOneModel 仅删除与过滤匹配的一个文档,而 DeleteManyModel 会删除与过滤匹配的所有文档。
下表描述了可以在 DeleteOneModel 或 DeleteManyModel 中设立的字段:
字段 | 说明 |
|---|---|
| 与要删除的一个或多个文档相匹配的过滤器。在 |
| (可选)对结果进行排序时使用的排序规则。要学习有关排序规则的更多信息,请参阅 排序规则部分的配置 CRUD 操作指南。 |
| (可选)用于操作的索引。要学习;了解有关索引的更多信息,请参阅 用于查询优化的索引 指南。 |
例子
此示例将执行以下动作:
在大量中指定一个
DeleteOneModel和一个DeleteManyModel实例。这些模型包含删除movies集合中文档的指令。在
movies集合上调用bulkWrite()方法,并将模型大量作为参数传递。打印已删除文档的数量。
const deleteOperations = [{ deleteOne: { filter: { title: "Dunkirk" } }}, { deleteMany: { filter: { rated: "R" } }}];
const deleteResult = await movies.bulkWrite(deleteOperations);console.log(`Deleted documents: ${deleteResult.deletedCount}`);客户端批量删除
要跨多个集合或数据库执行批量删除操作,请为每个操作创建一个 ClientBulkWriteModel。然后,在客户端上调用 bulkWrite() 方法并将模型大量作为参数传递。
下表描述了您可以在 ClientBulkWriteModel 中设立以指定删除操作的字段:
字段 | 说明 |
|---|---|
| 要在其中删除文档的命名空间空间。 |
| 要执行的操作。对于删除操作,请将此字段设立为 |
| 与要删除的一个或多个文档相匹配的过滤器。如果将模型 |
| (可选)用于操作的索引。要学习;了解有关索引的更多信息,请参阅 用于查询优化的索引 指南。 |
| (可选)对结果进行排序时使用的排序规则。要学习有关排序规则的更多信息,请参阅 排序规则部分的配置 CRUD 操作指南。 |
例子
此示例将执行以下动作:
在大量中指定两个
ClientBulkWriteModel实例。第一个模型指定对movies集合执行“删除多个”操作,第二个模型指定对users集合执行“删除一个”操作。在客户端上调用
bulkWrite()方法,并将模型大量作为参数传递。打印已修改文档的数量。
const clientDeletes = [{ namespace: "sample_mflix.movies", name: "deleteMany", filter: { rated: "R" }}, { namespace: "sample_mflix.users", name: "deleteOne", filter: { email: "emilia_clarke@gameofthron.es" }}];
const clientDeleteRes = await client.bulkWrite(clientDeletes);console.log(`Deleted documents: ${clientDeleteRes.deletedCount}`);返回类型
BulkWriteResult
Collection.bulkWrite() 方法返回一个 BulkWriteResult对象,其中提供有关批量操作的信息。
下表描述了 BulkWriteResult对象的字段:
字段 | 说明 |
|---|---|
| 插入文档的数量 |
| 匹配文档的数量 |
| 更新文档的数量 |
| 已更新或插入的文档数量 |
| 已删除文档的数量 |
ClientBulkWriteResult
MongoClient.bulkWrite() 方法返回一个 ClientBulkWriteResult对象,其中包含有关客户端端批量写入操作的信息。
下表描述了 ClientBulkWriteResult对象的字段:
字段 | 说明 |
|---|---|
| 指示批量写入是否已确认的布尔值 |
| 插入文档的数量 |
| 匹配文档的数量 |
| 更新文档的数量 |
| 已更新或插入的文档数量 |
| 已删除文档的数量 |
| 每个成功插入操作的结果 |
| 每个成功更新操作的结果 |
| 每个成功删除操作的结果 |
处理异常
集合批量写入异常
如果对集合调用的任何批量写入操作不成功,则当 ordered 选项设立为 true 时,Node.js驱动程序会抛出 MongoBulkWriteError,并且不会执行任何进一步的操作。如果将 ordered设立false,则会尝试继续后续操作。
提示
要学习;了解有关有序和无序批量操作的更多信息,请参阅MongoDB Server手册中批量写入指南中的有序与无序操作部分。
MongoBulkWriteError对象包含以下属性:
属性 | 说明 |
|---|---|
| 错误消息。 |
| 批量写入操作期间发生的错误的数组。 |
| 执行批量写入操作期间出现的写关注(write concern)错误。 |
| 在抛出异常之前成功执行的任何操作的结果。 |
| 根本的错误对象,其中可能包含更多详细信息。 |
客户端批量写入异常
如果在客户端上调用的任何批量写入操作不成功,Node.js驱动程序都会生成一个 MongoClientBulkWriteError。默认情况下,驱动程序在出现错误后不执行任何后续操作。如果将 ordered 选项传递给 bulkWrite() 方法并将其设立为 false,则驱动程序将继续尝试其余操作。
MongoClientBulkWriteError对象包含以下属性:
属性 | 说明 |
|---|---|
| 指定每个写关注(write concern)错误的文档数组。 |
| 单个写入操作期间发生的错误的映射。 |
| 客户端端批量写入的部分结果,反映了错误发生前的操作进度。 |
bulkWrite() 示例:完整文件
注意
设置示例
该示例使用连接 URI 连接到 MongoDB 实例。如需了解有关连接到 MongoDB 实例的更多信息,请参阅连接到 MongoDB 指南。本示例还使用了Atlas 示例数据集中包含的 sample_mflix 数据库中的 movies 集合。您可以按照 MongoDB 入门指南,将它们加载到 MongoDB Atlas 的免费集群数据库中。
以下代码是完整的独立运行文件,用于对 sample_mflix数据库中的 theaters集合执行批量写入操作。operations 参数包括 insertOne、updateMany 和 deleteOne写入操作的示例:
// Bulk write operation
// Import MongoClient from the MongoDB node driver packageconst { MongoClient } = require("mongodb");
// Replace the uri string with your MongoDB deployment's connection stringconst uri = "<connection string uri>";
const client = new MongoClient(uri);
async function run() { try { const database = client.db("sample_mflix"); const theaters = database.collection("theaters");
// Insert a new document into the "theaters" collection const result = await theaters.bulkWrite([ { insertOne: { document: { location: { address: { street1: "3 Main St.", city: "Anchorage", state: "AK", zipcode: "99501", }, }, }, }, }, { insertOne: { document: { location: { address: { street1: "75 Penn Plaza", city: "New York", state: "NY", zipcode: "10001", }, }, }, }, }, { // Update documents that match the specified filter updateMany: { filter: { "location.address.zipcode": "44011" }, update: { $set: { is_in_ohio: true } }, upsert: true, }, }, { // Delete a document that matches the specified filter deleteOne: { filter: { "location.address.street1": "221b Baker St" } }, }, ]); // Log the result of the bulk write operation console.log(result); } finally { // Close the database connection when the operations are completed or if an error occurs await client.close(); }}run().catch(console.dir);import { MongoClient } from "mongodb";
// Replace the uri string with your MongoDB deployment's connection string.const uri = "<connection string uri>";
const client = new MongoClient(uri);
interface Address { street1: string; city: string; state: string; zipcode: string;}
interface Theater { location: { address: Address }; is_in_ohio?: boolean;}
async function run() { try { const database = client.db("sample_mflix"); const theaters = database.collection<Theater>("theaters");
const result = await theaters.bulkWrite([ { insertOne: { document: { location: { address: { street1: "3 Main St.", city: "Anchorage", state: "AK", zipcode: "99501", }, }, }, }, }, { insertOne: { document: { location: { address: { street1: "75 Penn Plaza", city: "New York", state: "NY", zipcode: "10001", }, }, }, }, }, { updateMany: { // Important: You lose type safety when you use dot notation in queries filter: { "location.address.zipcode": "44011" }, update: { $set: { is_in_ohio: true } }, upsert: true, }, }, { deleteOne: { filter: { "location.address.street1": "221b Baker St" }, }, }, ]);
console.log(result); } finally { await client.close(); }}run().catch(console.dir);运行上述示例将产生以下输出:
BulkWriteResult { insertedCount: 2, matchedCount: 1, modifiedCount: 1, deletedCount: 0, upsertedCount: 0, upsertedIds: {}, insertedIds: { '0': new ObjectId("..."), '1': new ObjectId("...") }}更多信息
要学习;了解有关批量操作的更多信息,请参阅MongoDB Server手册中的批量写入操作。
API 文档
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: