2011-08-30 75 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不同。你能幫我麼? –