对于 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 菜单

替换文档

在本指南中,您可以学习如何使用C++驱动程序对MongoDB集合运行替换操作。替换操作会删除目标文档中除 _id字段之外的所有字段,并替换为新字段。您可以调用 replace_one() 方法来替换单个文档。

本指南中的示例使用Atlas示例数据集sample_restaurants数据库中的restaurants集合。 要从C++应用程序访问权限此集合,请实例化一个连接到Atlas 集群的mongocxx::client ,并将以下值分配给dbcollection变量:

auto db = client["sample_restaurants"];
auto collection = db["restaurants"];

要学习如何创建免费的MongoDB Atlas 集群并加载示例数据集,请参阅MongoDB 入门指南

您可以通过调用 replace_one() 方法来执行替换操作。此方法会从匹配搜索条件的第一个文档中删除除 _id字段之外的所有字段。然后,它将您指定的字段和值插入到文档中。

replace_one() 方法需要使用以下参数:

  • 查询过滤文档:指定要替换的文档。有关查询筛选器的更多信息,请参阅MongoDB Server手册中的查询筛选器文档。

  • 替换文档:指定要在新文档中插入的字段和值。

重要

_id 字段的值不可变。如果您的替换文档指定 _id 字段的值,则它必须与现有文档的 _id 值匹配。

以下示例使用 replace_one() 方法将 name字段值为 "Nobu" 的文档替换为 name字段值为 "La Bernadin" 的新文档:

auto query_filter = make_document(kvp("name", "Nobu"));
auto replace_doc = make_document(kvp("name", "La Bernadin"));
auto result = collection.replace_one(query_filter.view(), replace_doc.view());

要检查是否成功替换了文档,可以使用 find_one() 方法打印出新文档:

auto new_doc = collection.find_one(make_document(kvp("name", "La Bernadin")));
std::cout << "New document: " << bsoncxx::to_json(*new_doc) << std::endl;
New document: { "_id" : { "$oid" : "..." }, "name" : "La Bernadin" }

要了解有关find_one()方法的更多信息,请参阅“检索数据”指南中的“查找一个文档”。

您可以通过将 mongocxx::options::replace 类的实例作为可选参数传递来修改 replace_one() 方法的行为。下表描述了您可以在 mongocxx::options::replace实例中设立的字段:

字段
说明

bypass_document_validation

指定替换操作是否绕过文档验证。当设立为true 时,您可以用不符合模式验证要求的新文档替换文档。有关更多信息,请参阅MongoDB Server手册中的模式验证。默认为
false

collation

指定对结果进行排序时要使用的语言排序规则类型。 有关更多信息,请参阅 MongoDB Server 手册中的排序规则

comment

指定要附加到操作的任何有效BSON类型的注释。 设立后,该注释将与该命令的记录一起出现在以下位置:

有关更多信息,请参阅MongoDB Server手册中的插入命令字段指南。

hint

指定索引以扫描与查询过滤匹配的文档。 有关更多信息,请参阅MongoDB Server手册中的提示字段。

let

指定包含要在 replace_one() 方法中使用的变量及其值的文档。 这样,您就可以将变量与操作文本分开,从而提高代码的可读性。 值必须是常量或不引用文档字段的闭合表达式。 有关更多信息,请参阅MongoDB Server手册中的 let字段。

upsert

指定在没有文档与查询过滤匹配的情况下,替换操作是否执行更新或插入(upsert)操作。默认为
false

write_concern

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

以下示例使用 create_index() 方法在 name字段上创建升序单字段索引。然后,将 hint字段设置为新索引后,将 mongocxx::options::replace对象传递给 replace_one() 方法。这指示替换操作在替换 name字段值为 "Nobu" 的文档时搜索name字段索引:

auto index_specification = make_document(kvp("name", 1));
collection.create_index(index_specification.view());
mongocxx::options::replace opts{};
opts.hint(mongocxx::hint{"name_1"});
auto query_filter = make_document(kvp("name", "Nobu"));
auto replace_doc = make_document(kvp("name", "La Bernadin"));
auto result = collection.replace_one(query_filter.view(), replace_doc.view(), opts);

要学习;了解有关索引的更多信息,请参阅《使用索引优化查询》指南。

以下示例将 mongocxx::options::replace对象的 upsert字段值设置为 true 后,将其传递给 replace_one() 方法。由于没有与查询过滤匹配的文档,因此这会指示替换操作将 name字段值为 "Shake Shack" 的新文档插入到集合中:

std::cout << "Total document count before replace_one(): " << collection.count_documents({}) << std::endl;
mongocxx::options::replace opts{};
opts.upsert(true);
auto query_filter = make_document(kvp("name", "In-N-Out Burger"));
auto replace_doc = make_document(kvp("name", "Shake Shack"));
auto result = collection.replace_one(query_filter.view(), replace_doc.view(), opts);
std::cout << "Total document count after replace_one(): " << collection.count_documents({}) << std::endl;
Total document count before replace_one(): 25359
Total document count after replace_one(): 25360

replace_one() 方法返回 mongocxx::result::replace 类的实例。该类包含以下成员函数:

function
说明

matched_count()

返回与查询过滤匹配的文档数,无论替换了多少文档。

modified_count()

返回替换操作修改的文档数。 如果替换的文档与原始文档相同,则不计入此计数。

result()

返回操作的批量写入结果。

upserted_id()

如果驱动程序执行了更新或插入(upsert),则返回在数据库中更新或插入的文档的ID。

以下示例使用 replace_one() 方法将 name字段值为 "Shake Shack" 的文档替换为 name字段值为 "In-N-Out Burger" 的新文档。然后,它调用 matched_count() 成员函数来打印与查询过滤匹配的文档数量:

auto query_filter = make_document(kvp("name", "Shake Shack"));
auto replace_doc = make_document(kvp("name", "In-N-Out Burger"));
auto result = collection.replace_one(query_filter.view(), replace_doc.view());
std::cout << "Matched documents: " << result->matched_count() << std::endl;
Matched documents: 11

以下示例使用 replace_one() 方法替换 name字段值为 "In-N-Out Burger" 的文档。由于 upsert 选项设立为 true,因此当查询筛选条件与任何现有文档都不匹配时, C++驱动程序会插入一个新文档。然后,代码调用 upserted_id() 节点函数来打印已更新或插入的文档的 _id字段值:

mongocxx::options::replace opts{};
opts.upsert(true);
auto query_filter = make_document(kvp("name", "In-N-Out Burger"));
auto replace_doc = make_document(kvp("name", "Shake Shack"));
auto result = collection.replace_one(query_filter.view(), replace_doc.view(), opts);
auto id = result->upserted_id()->get_value();
std::cout << "Upserted ID: " << id.get_oid().value.to_string() << std::endl;
// Your ID value may differ
Upserted ID: 67128c5ecc1f8c15ea26fcf8

要了解创建查询筛选器的更多信息,请参阅指定查询指南。

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