文档菜单
文档首页
/ / /
C#/.NET
/ / /

修改文档

本页内容

  • 概述
  • 示例数据
  • 更新操作
  • 必需参数
  • 更新单个文档
  • 更新多个文档
  • 自定义更新操作
  • 返回值
  • 示例
  • 替换操作
  • 必需参数
  • 自定义替换操作
  • 返回值
  • 示例
  • 更多信息
  • API 文档

在此指南中,您可以了解如何使用 MongoDB .NET/C# 驱动程序通过以下操作修改 MongoDB 集合中的文档:

  • 更新操作

  • 替换操作

.NET/C# 驱动程序提供了以下方法来修改文档,每个方法都有异步和同步版本:

  • UpdateOneAsync()UpdateOne()

  • UpdateManyAsync()UpdateMany()

  • ReplaceOneAsync()ReplaceOne()

提示

交互式实验室

此页面包含一个简短的交互式实验室,演示了如何使用 UpdateManyAsync() 方法修改数据。您可以直接在浏览器窗口中完成此实验室,无需安装 MongoDB 或代码编辑器。

要启动实验室,请单击打开交互式教程 按钮。要将实验室扩展到全屏格式,请单击实验室面板右上角的全屏按钮()。

本指南中的示例使用 sample_restaurants 数据库中的 restaurants 集合。此集合中的文档使用以下 RestaurantAddressGradeEntry 类作为模型。

public class Restaurant
{
public ObjectId Id { get; set; }
public string Name { get; set; }
[BsonElement("restaurant_id")]
public string RestaurantId { get; set; }
public string Cuisine { get; set; }
public Address Address { get; set; }
public string Borough { get; set; }
public List<GradeEntry> Grades { get; set; }
}
public class Address
{
public string Building { get; set; }
[BsonElement("coord")]
public double[] Coordinates { get; set; }
public string Street { get; set; }
[BsonElement("zipcode")]
public string ZipCode { get; set; }
}
public class GradeEntry
{
public DateTime Date { get; set; }
public string Grade { get; set; }
public float? Score { get; set; }
}

注意

在“restaurants”集合中,文档使用蛇形命名约定。本指南中的示例使用一个ConventionPack将集合中的字段反序列化为帕斯卡命名法,并将它们映射到Restaurant类中的属性。

要了解更多关于自定义序列化的信息,请参阅自定义序列化.

此集合来自Atlas提供的示例数据集。查看快速入门以了解如何创建免费的MongoDB集群并加载此示例数据。

您可以使用以下方法在MongoDB中执行更新操作

  • UpdateOne(),它更新符合搜索条件的第一个文档

  • UpdateMany(),它更新所有符合搜索条件的文档

每个更新方法都需要以下参数

  • 一个查询过滤器文档,它确定要更新的记录。有关查询过滤器的更多信息,请参阅MongoDB服务器手册

  • 一个更新文档,它指定了更新操作符(要执行的类型更新)以及应更改的字段和值。有关更新操作符的完整列表及其用法,请参阅字段更新操作符手册页面

.NET/C#驱动程序提供了一个Builders类,该类简化了查询过滤器和更新文档的创建。以下代码示例使用Builders创建两个文档,用于作为更新操作参数

  • 一个查询过滤器,用于搜索具有“cuisine”字段值为“Pizza”的餐厅

  • 一个更新文档,将这些餐厅的“cuisine”字段值设置为“Pasta and breadsticks”

const string oldValue = "Pizza";
const string newValue = "Pasta and breadsticks";
// Creates a filter for all documents with a "cuisine" value of "Pizza"
var filter = Builders<Restaurant>.Filter
.Eq(restaurant => restaurant.Cuisine, oldValue);
// Creates instructions to update the "cuisine" field of documents that
// match the filter
var update = Builders<Restaurant>.Update
.Set(restaurant => restaurant.Cuisine, newValue);
// Updates all documents that have a "cuisine" value of "Pizza"
return _restaurantsCollection.UpdateMany(filter, update);

提示

更新操作中的聚合管道

如果您使用的是 MongoDB 版本 4.2 或更高版本,您可以在更新操作中使用由聚合阶段的子集组成的聚合管道。有关 MongoDB 在更新操作中支持的聚合阶段的更多信息,请参阅我们关于使用聚合管道进行更新的教程 使用聚合管道更新文档。

以下代码展示了如何使用异步的 UpdateOneAsync() 方法或同步的 UpdateOne() 方法来更新单个文档。

var result = await _restaurantsCollection.UpdateOneAsync(filter, update);
var result = _restaurantsCollection.UpdateOne(filter, update);

以下代码展示了如何使用异步的 UpdateManyAsync() 方法或同步的 UpdateMany() 方法来更新所有匹配的文档。

var result = await _restaurantsCollection.UpdateManyAsync(filter, update);
var result = _restaurantsCollection.UpdateMany(filter, update);

提示

在这些方法的可运行示例中,请参阅更多信息。

两种方法都可选地接受一个UpdateOptions对象作为附加参数,该对象表示您可以使用它来配置更新操作。如果您没有指定任何UpdateOptions属性,则驱动程序不会自定义更新操作。

UpdateOptions类型允许您使用以下属性配置选项

属性
描述

ArrayFilters

指定对数组字段进行更新操作时应修改哪些数组元素。有关更多信息,请参阅MongoDB服务器手册

BypassDocumentValidation

指定更新操作是否绕过文档验证。这允许您更新不满足模式验证要求的文档(如果存在)。有关模式验证的更多信息,请参阅MongoDB服务器手册

Collation

指定排序结果时使用的语言排序规则类型。有关排序规则的更多信息,请参阅MongoDB服务器手册

Comment

获取或设置操作的用户提供的注释。有关更多信息,请参阅MongoDB服务器手册

Hint

获取或设置用于扫描文档的索引。有关更多信息,请参阅MongoDB服务器手册

IsUpsert

指定更新操作是否在查询过滤器没有匹配的文档时执行更新操作。有关更多信息,请参阅MongoDB服务器手册

Let

获取或设置let文档。有关更多信息,请参阅MongoDB服务器手册

方法 UpdateOne()UpdateMany() 每个都返回一个 UpdateResult 对象。类型 UpdateResult 包含以下属性

属性
描述

IsAcknowledged

指示 MongoDB 是否已确认更新操作。

IsModifiedCountAvailable

指示是否可以在 UpdateResult 中读取已更新记录的计数。

MatchedCount

匹配查询过滤器的文档数量,无论更新了多少。

ModifiedCount

更新操作更新的文档数量。如果更新的文档与原始文档相同,则不会包含在此计数中。

UpsertedId

如果驱动程序执行了 upsert,则是在数据库中 upsert 的文档的 ID。

以下代码使用 UpdateMany() 方法查找所有 borough 字段值为 "Manhattan" 的文档,然后将这些文档中的 borough 值更新为 "Manhattan (north)"。因为将 IsUpsert 选项设置为 true,如果查询过滤器与任何现有文档不匹配,则驱动程序将插入一个新文档。

var filter = Builders<Restaurant>.Filter
.Eq(restaurant => restaurant.Borough, "Manhattan");
var update = Builders<Restaurant>.Update
.Set(restaurant => restaurant.Borough, "Manhattan (north)");
UpdateOptions opts = new UpdateOptions()
{
Comment = new BsonString("Borough updated for C# Driver Fundamentals"),
IsUpsert = true
};
Console.WriteLine("Updating documents...");
var result = _restaurantsCollection.UpdateMany(filter, update, opts);
Console.WriteLine($"Updated documents: {result.ModifiedCount}");
Console.WriteLine($"Result acknowledged? {result.IsAcknowledged}");
Updating documents...
Updated documents: 10259
Result acknowledged? True

注意

如果前面的示例使用的是 UpdateOne() 方法而不是 UpdateMany(),则驱动程序将只更新匹配的文档中的第一个。

您可以使用MongoDB中的ReplaceOne()方法执行替换操作。此方法删除与搜索条件匹配的第一个文档的所有字段(除_id字段外),然后将您指定的字段和值插入到文档中。

ReplaceOne()方法需要以下参数

  • 查询过滤器文档,用于确定要替换的记录。

  • 替换文档,指定要插入新文档中的字段和值。如果您的集合中的文档映射到一个C#类,则替换文档可以是此类的一个实例。

与更新操作类似,您可以在.NET/C#驱动程序中使用Builders类创建查询过滤器。以下代码示例使用Builders创建一个查询过滤器,用于搜索具有name字段值为"Pizza Town"的餐厅。该代码还创建了一个新的Restaurant对象,该对象将替换第一个匹配的文档。

// Creates a filter for all restaurant documents that have a "cuisine" value of "Pizza"
var filter = Builders<Restaurant>.Filter
.Eq(r => r.Cuisine, "Pizza");
// Finds the ID of the first restaurant document that matches the filter
var oldPizzaRestaurant = _restaurantsCollection.Find(filter).First();
var oldId = oldPizzaRestaurant.Id;
// Generates a new restaurant document
Restaurant newPizzaRestaurant = new()
{
Id = oldId,
Name = "Mongo's Pizza",
Cuisine = "Pizza",
Address = new()
{
Street = "Pizza St",
ZipCode = "10003"
},
Borough = "Manhattan",
};
// Replaces the existing restaurant document with the new document
return _restaurantsCollection.ReplaceOne(filter, newPizzaRestaurant);

重要

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

以下代码演示了如何使用异步的ReplaceOneAsync()方法或同步的ReplaceOne()方法替换一个文档。

var result = await _restaurantsCollection.ReplaceOneAsync(filter, newRestaurant);
var result = _restaurantsCollection.ReplaceOne(filter, newRestaurant);

提示

在这些方法的可运行示例中,请参阅更多信息。

ReplaceOne() 方法可选地接受一个 ReplaceOptions 对象作为附加参数,该对象表示可以用来配置替换操作的选项。如果您不指定任何 ReplaceOptions 属性,则驱动程序不会自定义替换操作。

ReplaceOptions 类型允许您使用以下属性来配置选项

属性
描述

BypassDocumentValidation

指定替换操作是否绕过文档验证。这允许您替换不符合模式验证要求的文档(如果存在)。有关模式验证的更多信息,请参阅 MongoDB 服务器手册

Collation

指定排序结果时使用的语言排序规则类型。有关排序规则的更多信息,请参阅MongoDB服务器手册

Comment

获取或设置操作的用户提供的注释。有关更多信息,请参阅MongoDB服务器手册

Hint

获取或设置用于扫描文档的索引。有关更多信息,请参阅MongoDB服务器手册

IsUpsert

指定如果查询过滤器没有匹配的文档,则替换操作是否执行更新操作。有关更多信息,请参阅 MongoDB 服务器手册

Let

获取或设置let文档。有关更多信息,请参阅MongoDB服务器手册

ReplaceOne() 方法返回一个 ReplaceOneResult 对象。该 ReplaceOneResult 类型包含以下属性

属性
描述

IsAcknowledged

指示替换操作是否被 MongoDB 确认。

IsModifiedCountAvailable

指示您是否可以读取 ReplaceOneResult 上的替换记录数。

MatchedCount

匹配查询过滤器的文档数,无论是否有一个被替换。

ModifiedCount

替换操作替换的文档数。

UpsertedId

如果驱动程序执行了 upsert,则是在数据库中 upsert 的文档的 ID。

以下代码使用ReplaceOne()方法查找第一个name字段值为"Pizza Town"的文档,然后将其替换为一个新的名为"Food World"的Restaurant文档。由于将IsUpsert选项设置为true,如果查询过滤器与任何现有文档不匹配,则驱动程序将插入一个新的文档。

var filter = Builders<Restaurant>.Filter.Eq(restaurant => restaurant.Name, "Pizza Town");
Restaurant newRestaurant = new()
{
Name = "Food World",
Cuisine = "American",
Address = new BsonDocument
{
{"street", "Food St"},
{"zipcode", "10003"},
},
Borough = "Manhattan",
};
ReplaceOptions opts = new ReplaceOptions()
{
Comment = new BsonString("Restaurant replaced for .NET/C# Driver Fundamentals"),
IsUpsert = true
};
Console.WriteLine("Replacing document...");
var result = _restaurantsCollection.ReplaceOne(filter, newRestaurant, opts);
Console.WriteLine($"Replaced documents: {result.ModifiedCount}");
Console.WriteLine($"Result acknowledged? {result.IsAcknowledged}");
Replacing document...
Replaced documents: 1
Result acknowledged? True

有关更新和替换操作的运行示例,请参阅以下使用示例

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

要了解更多关于本指南中讨论的任何方法或类型的信息,请参阅以下API文档

返回

插入