简体   繁体   English

使用官方 C# 驱动程序在 Mongo DB 中更新

[英]Upserting in Mongo DB using official C# driver

In the official documentation of mongodb they mention upserts, so it would be really nice to write an upsert command instead of:在 mongodb 的官方文档中他们提到了 upserts,所以写一个 upsert 命令而不是:

if (_campaignRepo.Exists(camp))
{
    _campaignRepo.DeleteByIdAndSystemId(camp);
}

_campaignRepo.Save(camp);

something which would implement that logic on the db level if it is possible.如果可能的话,可以在数据库级别实现该逻辑的东西。 So what is the way to do an upsert if there is one?那么如果有一个 upsert,有什么方法呢?

Version 2 of the MongoDB C# driver requires setting the IsUpsert flag in the write commands. MongoDB C# 驱动程序的版本 2需要在写入命令中设置IsUpsert标志。 This example will upsert an entire document.此示例将插入整个文档。

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);

Version 1 of the MongoDB C# driver implements this logic within the Save command. MongoDB C# 驱动程序的第 1 版Save命令中实现了此逻辑。

var newDoc = new BsonDocument { { "_id", 123 }, { "someKey", "someValue" } };
collection.Save(newDoc);

The Save method is a combination of Insert and Update. Save 方法是 Insert 和 Update 的组合。 If the Id member of the document has a value, then it is assumed to be an existing document and Save calls Update on the document (setting the Upsert flag just in case it actually is a new document after all).如果文档的 Id 成员有一个值,则假定它是一个现有文档,并且 Save 调用该文档的 Update(设置 Upsert 标志以防它实际上是一个新文档)。 Otherwise it is assumed to be a new document and Save calls Insert after first assigning a newly generated unique value to the Id member.否则,它被假定为一个新文档,并且 Save 在第一次将新生成的唯一值分配给 Id 成员后调用 Insert。

Reference: http://mongodb.github.io/mongo-csharp-driver/1.11/driver/#save-tdocument-method参考: http : //mongodb.github.io/mongo-csharp-driver/1.11/driver/#save-tdocument-method

Note: This does require the proper mapping of the Id field however.注意:这确实需要正确映射 Id 字段。 More info on that here: http://mongodb.github.io/mongo-csharp-driver/1.11/serialization/#identifying-the-id-field-or-property更多信息在这里: http : //mongodb.github.io/mongo-csharp-driver/1.11/serialization/#identifying-the-id-field-or-property

Starting from v2.0 of the driver there's a new async-only API.从驱动程序的 v2.0 开始,有一个新的仅异步 API。 The old API should no longer be used as it's a blocking facade over the new API and is deprecated.不应再使用旧 API,因为它是新 API 的阻塞外观,已弃用。

The currently recommended way to upsert a document is by calling and awaiting ReplaceOneAsync with the IsUpsert flag turned on and a filter that matches the relevant document:当前推荐的插入文档的方法是调用并等待ReplaceOneAsync并打开IsUpsert标志和匹配相关文档的过滤器:

Hamster hamster = ...
var replaceOneResult = await collection.ReplaceOneAsync(
    doc => doc.Id == hamster.Id, 
    hamster, 
    new UpdateOptions {IsUpsert = true});

You can check whether the operation was an insert or an update by looking at ReplaceOneResult.MatchedCount :您可以通过查看ReplaceOneResult.MatchedCount来检查操作是插入还是更新:

The following code is from a working app:以下代码来自一个工作应用程序:

weekplanStore.Update(
    Query.EQ("weekNumber", week),
    Update.Replace(rawWeekPlan),
    UpdateFlags.Upsert);

The weekplanStore is my MongoDB collection, and the code will update the document found with the query in the first argument or insert a new one if none is found. weekplanStore 是我的 MongoDB 集合,代码将更新在第一个参数中使用查询找到的文档,或者如果没有找到则插入一个新文档。 The "trick" is to use the UpdateFlags.Upsert modifier. “技巧”是使用 UpdateFlags.Upsert 修饰符。

The rawWeekPlan is the object inserted or updated, and has the following type: rawWeekPlan 是插入或更新的对象,具有以下类型:

private class RawWeekPlan
{
    public ObjectId id;
    public int weekNumber;
    public WeekPlanEntry[] entries;
}

and turned into bson by the driver automatically.并被驱动自动变成bson。

You can use the regular update command, but just pass it the Upsert update flag您可以使用常规更新命令,但只需将 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);

That code is adapted from a working application (shortened for clarity)该代码改编自一个工作应用程序(为了清楚起见缩短了)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM