Overview
在本指南中,您可以了解如何使用 Node.js 驱动程序执行批量操作。批量操作有助于减少对服务器的调用次数。您可以在一次执行多个操作,而不是为每个操作发送请求。
提示
要学习;了解有关批量操作的更多信息,请参阅MongoDB Server手册中的批量写入操作。
您可以使用批量操作对集合执行多个写入操作。您还可以从客户端运行批量操作,这样就可以跨多个命名空间执行批量写入。在MongoDB中,命名空间由数据库名称和集合名称组成,格式为 <database>.<collection>。
本指南包括以下部分:
批量插入操作描述了如何在集合或客户端上执行批量插入操作。
批量替换操作描述了如何在集合或客户端上执行批量替换操作。
批量更新操作描述了如何在集合或客户端上执行批量更新操作。
批量删除操作描述了如何在集合或客户端上执行批量删除操作。
其他信息提供了指向本指南中提及的类型和方法的资源和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}`);
Inserted documents: 2
客户端批量插入
要跨多个集合或数据库执行批量插入操作,请为每个操作创建一个 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}`);
Inserted documents: 3
批量替换操作
要执行批量替换操作,请为要替换的每个文档创建批量操作模型。然后,将这些模型的列表传递给 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}`);
Modified documents: 2
客户端批量替换
要跨多个集合或数据库执行批量替换操作,请为每个操作创建一个 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}`);
Modified documents: 3
批量更新操作
要执行批量更新操作,请为要进行的每个更新创建批量操作模型。然后,将这些模型的列表传递给 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}`);
Modified documents: 2320
客户端批量更新
要跨多个集合或数据库执行批量更新操作,请为每个操作创建一个 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}`);
Modified documents: 2320
批量删除操作
要执行批量删除操作,请为每个删除操作创建批量操作模型。然后,将这些模型的列表传递给 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}`);
Deleted documents: 5538
客户端批量删除
要跨多个集合或数据库执行批量删除操作,请为每个操作创建一个 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}`);
Deleted documents: 5538
返回类型
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() 示例:完整文件
注意
设置示例
This example connects to an instance of MongoDB by using a connection URI. To learn more about connecting to your MongoDB instance, see the Connect to MongoDB guide. This example also uses the movies collection in the sample_mflix database included in the Atlas sample datasets. You can load them into your database on the free tier of MongoDB Atlas by following the MongoDB Get Started.
以下代码是完整的独立运行文件,用于对 sample_mflix数据库中的 theaters集合执行批量写入操作。operations 参数包括 insertOne、updateMany 和 deleteOne写入操作的示例:
1 // Bulk write operation 2 3 // Import MongoClient from the MongoDB node driver package 4 const { MongoClient } = require("mongodb"); 5 6 // Replace the uri string with your MongoDB deployment's connection string 7 const uri = "<connection string uri>"; 8 9 const client = new MongoClient(uri); 10 11 async function run() { 12 try { 13 const database = client.db("sample_mflix"); 14 const theaters = database.collection("theaters"); 15 16 // Insert a new document into the "theaters" collection 17 const result = await theaters.bulkWrite([ 18 { 19 insertOne: { 20 document: { 21 location: { 22 address: { 23 street1: "3 Main St.", 24 city: "Anchorage", 25 state: "AK", 26 zipcode: "99501", 27 }, 28 }, 29 }, 30 }, 31 }, 32 { 33 insertOne: { 34 document: { 35 location: { 36 address: { 37 street1: "75 Penn Plaza", 38 city: "New York", 39 state: "NY", 40 zipcode: "10001", 41 }, 42 }, 43 }, 44 }, 45 }, 46 { 47 // Update documents that match the specified filter 48 updateMany: { 49 filter: { "location.address.zipcode": "44011" }, 50 update: { $set: { is_in_ohio: true } }, 51 upsert: true, 52 }, 53 }, 54 { 55 // Delete a document that matches the specified filter 56 deleteOne: { filter: { "location.address.street1": "221b Baker St" } }, 57 }, 58 ]); 59 // Log the result of the bulk write operation 60 console.log(result); 61 } finally { 62 // Close the database connection when the operations are completed or if an error occurs 63 await client.close(); 64 } 65 } 66 run().catch(console.dir);
1 import { MongoClient } from "mongodb"; 2 3 // Replace the uri string with your MongoDB deployment's connection string. 4 const uri = "<connection string uri>"; 5 6 const client = new MongoClient(uri); 7 8 interface Address { 9 street1: string; 10 city: string; 11 state: string; 12 zipcode: string; 13 } 14 15 interface Theater { 16 location: { address: Address }; 17 is_in_ohio?: boolean; 18 } 19 20 async function run() { 21 try { 22 const database = client.db("sample_mflix"); 23 const theaters = database.collection<Theater>("theaters"); 24 25 const result = await theaters.bulkWrite([ 26 { 27 insertOne: { 28 document: { 29 location: { 30 address: { 31 street1: "3 Main St.", 32 city: "Anchorage", 33 state: "AK", 34 zipcode: "99501", 35 }, 36 }, 37 }, 38 }, 39 }, 40 { 41 insertOne: { 42 document: { 43 location: { 44 address: { 45 street1: "75 Penn Plaza", 46 city: "New York", 47 state: "NY", 48 zipcode: "10001", 49 }, 50 }, 51 }, 52 }, 53 }, 54 { 55 updateMany: { 56 // Important: You lose type safety when you use dot notation in queries 57 filter: { "location.address.zipcode": "44011" }, 58 update: { $set: { is_in_ohio: true } }, 59 upsert: true, 60 }, 61 }, 62 { 63 deleteOne: { 64 filter: { "location.address.street1": "221b Baker St" }, 65 }, 66 }, 67 ]); 68 69 console.log(result); 70 } finally { 71 await client.close(); 72 } 73 } 74 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 文档: