使用官方 C# 驱动程序在 Mongo DB 中进行更新插入
Posted
技术标签:
【中文标题】使用官方 C# 驱动程序在 Mongo DB 中进行更新插入【英文标题】:Upserting in Mongo DB using official C# driver 【发布时间】:2011-08-30 07:36:34 【问题描述】:在 mongodb 的官方文档中,他们提到了 upserts,所以写一个 upsert 命令而不是:
if (_campaignRepo.Exists(camp))
_campaignRepo.DeleteByIdAndSystemId(camp);
_campaignRepo.Save(camp);
如果可能的话,可以在数据库级别实现该逻辑的东西。那么如果有一个 upsert 的方法是什么?
【问题讨论】:
【参考方案1】:版本 2 的 MongoDB C# 驱动程序需要在写入命令中设置 IsUpsert
标志。此示例将 upsert 整个文档。
var newDoc = new BsonDocument "_id", 123 , "someKey", "someValue" ;
var result = await collection.ReplaceOneAsync(
filter: new BsonDocument("_id", 123),
options: new ReplaceOptions IsUpsert = true ,
replacement: newDoc);
版本 1 的 MongoDB C# 驱动程序在 Save
命令中实现此逻辑。
var newDoc = new BsonDocument "_id", 123 , "someKey", "someValue" ;
collection.Save(newDoc);
Save 方法是 Insert 和 Update 的组合。 如果文档的 Id 成员有值,则假定它是现有文档,并且 Save 调用文档上的 Update(设置Upsert 标志以防万一它毕竟是一个新文档)。否则,假定它是一个新文档,并且 Save 在首先将新生成的唯一值分配给 Id 成员后调用 Insert。
参考:http://mongodb.github.io/mongo-csharp-driver/1.11/driver/#save-tdocument-method
注意:但这确实需要正确映射 Id 字段。更多信息在这里:http://mongodb.github.io/mongo-csharp-driver/1.11/serialization/#identifying-the-id-field-or-property
【讨论】:
新 API 无法再做到这一点。 已更新。虽然我认为新的 API 使 upsert 命令更难使用。 如果 newDocs ID 为空,即它是一个插入,则传递给过滤器的内容是什么?只是一个空的 bson 文档? @BenCr 如果您只是进行普通插入而不是 upsert,那么您应该使用InsertOneAsync
方法。这不需要指定 ID 字段,因为 MongoDB 将在插入期间创建一个,但您也可以创建这些 ID,而无需像 GUID 一样进入数据库,因此这取决于您。 C# 驱动程序文档中的更多信息:mongodb.github.io/mongo-csharp-driver/2.1/reference/driver/crud/…【参考方案2】:
从驱动程序的 v2.0 开始,有一个新的仅异步 API。不应再使用旧 API,因为它是新 API 的阻塞外观,已被弃用。
目前推荐的 upsert 文档方法是调用并等待 ReplaceOneAsync
并打开 IsUpsert
标志并使用与相关文档匹配的过滤器:
Hamster hamster = ...
var replaceOneResult = await collection.ReplaceOneAsync(
doc => doc.Id == hamster.Id,
hamster,
new UpdateOptions IsUpsert = true);
您可以通过查看ReplaceOneResult.MatchedCount
来检查操作是插入还是更新:
【讨论】:
我正在尝试使用 ReplaceOneAsync 但它引发异常:“元素名称''无效”,我正在使用 updateOneasync 的过滤器,它可以工作但不能与 replaceone 一起使用。你能帮帮我吗? UpdateOptions 已过时,使用新的 ReplaceOptions IsUpsert = true);现在【参考方案3】:以下代码来自工作应用:
weekplanStore.Update(
Query.EQ("weekNumber", week),
Update.Replace(rawWeekPlan),
UpdateFlags.Upsert);
weekplanStore 是我的 MongoDB 集合,代码将使用第一个参数中的查询更新找到的文档,如果没有找到,则插入一个新文档。 “诀窍”是使用 UpdateFlags.Upsert 修饰符。
rawWeekPlan 是插入或更新的对象,具有以下类型:
private class RawWeekPlan
public ObjectId id;
public int weekNumber;
public WeekPlanEntry[] entries;
并被驱动自动转成bson。
【讨论】:
它适用于嵌套集合吗?你试过了吗?因为在我的情况下它对他们不起作用【参考方案4】:您可以使用常规更新命令,但只需将 Upsert 更新标志传递给它
MongoCollection collection = db.GetCollection("matches");
var query = new QueryDocument("recordId", recordId);
var update = Update.Set("FirstName", "John").Set("LastName","Doe");
matchCollection.Update(query, update, UpdateFlags.Upsert, SafeMode.False);
该代码改编自工作应用程序(为清楚起见而缩短)
【讨论】:
以上是关于使用官方 C# 驱动程序在 Mongo DB 中进行更新插入的主要内容,如果未能解决你的问题,请参考以下文章