2011-08-30 70 views
23

在他们提到upserts的MongoDB的官方文档,所以这将是非常好的写UPSERT命令代替:Upserting在蒙戈DB使用官方的C#驱动

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

_campaignRepo.Save(camp); 

一些东西,将实施对这一逻辑数据库级别,如果可能的话。那么如果有的话,做什么方法可以做什么?

回答

25

下面的代码是从工作程序:

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。

+0

它适用于嵌套集合吗?你试过了吗?因为它不适合他们在我的情况下 –

+0

不知道。我没有尝试过嵌套集合。 –

+0

问题出在id-s。我问了另一个线程上的问题 –

39

版本2的MongoDB C#驱动程序需要在写入命令中设置IsUpsert标志。本示例将插入整个文档。

var newDoc = new BsonDocument { { "_id", 123 }, { "someKey", "someValue" } }; 
var result = await collection.ReplaceOneAsync(
    filter: new BsonDocument("_id", 123), 
    options: new UpdateOptions { IsUpsert = true } 
    replacement: newDoc); 

版MongoDB的C#驱动器的1实现Save命令内此逻辑。

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

的保存方法是插入和更新的组合。如果文档的Id成员有一个值,则假定它是现有文档并在文档上保存调用Update(设置Upsert标志,以防万一它实际上是新文档)。否则,在首先将新生成的唯一值分配给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

+0

这对于新的API不再可行。 –

+0

已更新。尽管我认为新的API使得upsert命令更难使用。 –

+0

如果newDocs ID为null,即它是插入,那么传递给过滤器的是什么?只是一个空的BBS文件? – BenCr

5

您可以使用常规的更新命令,但只是通过它的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); 

该代码是从工作的应用程序(简称为清楚起见)

21

从V2.0开始适应驱动程序有一个新的异步API。不应该再使用旧的API,因为它是新API的屏蔽外观,因此不推荐使用。

目前推荐的方法来更新插入的文件是通过调用并等待ReplaceOneAsyncIsUpsert标志开启,并且有关文件相匹配的过滤器:

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

您可以检查操作是否插入或通过查看ReplaceOneResult.MatchedCount进行更新:

+0

我想使用ReplaceOneAsync,但它会引发异常:“元素名称”无效“,我正在使用updateOneasync的过滤器,但它的工作原理与replaceone不同。你能帮我么? –