2016-11-10 87 views
1

我有一個對象補丁REST API到部分更新的MongoDB在.NET

{ 
    "_id": "testobject", 
    "A": "First line", 
    "B": "Second line", 
    "C": "Third line" 
} 

我想發出一個REST PATCH請求我的API只更新這些屬性之一

{ 
    "_id": "testobject", 
    "C": "Forth line" 
} 

這被解析成一個類

public class SomeObject { 
    public string A { get; set; } 
    public string B { get; set; } 
    public string C { get; set; } 
} 

我現在需要更新MongoDB中的現有文檔,但只更新屬性C

我可以只爲這一個記錄創建更新定義

UpdateDefinition<SomeObject> update = Builders<SomeObject>.Update.Set(x => x.C, <value of property C>) 

或者我可以硬上的每個屬性代碼進行檢查,看它是否是空的

IList<UpdateDefinition<SomeObject>> updates = new List<UpdateDefinition<SomeObject>>(); 
if (!string.IsNullOrEmpty(C)) { 
    updates.Add(UpdateDefinition<SomeObject> update = Builders<SomeObject>.Update.Set(x => x.C, <value of property C>)); 
} 
if (!string.IsNullOrEmpty(C)) { 
    updates.Add(UpdateDefinition<SomeObject> update = Builders<SomeObject>.Update.Set(x => x.C, <value of property C>)); 
} 

但是,如果我有許多屬性和許多子屬性可能會非常快速地變大。另一個問題是,如果我設置的屬性的值是有意空的話,那就不是在所有因它找外地的非空更新記錄。

我如何做動態部分更新MongoDB的文檔.NET讓我有一個通用的PATCH API調用,可以採取任何文檔具有參數,只有指定的屬性更新?

回答

1

您可以使用

IMongoUpdate updateDoc = new UpdateDocument("$set", doc); 
collection.Update(Query.EQ("_id",id), updateDoc); 

但是,你要小心。

如果先反序列化文檔到SomeObject,所有的字段會得到他們的默認值(空字符串,0爲整數等)。如果您使用該對象進行更新,那麼您的json字符串中不存在的字段將更新爲其默認值。

如果使用

var bsonDoc = BsonSerializer.Deserialize<BsonDocument>(jsonString); 
IMongoUpdate updateDoc = new UpdateDocument("$set", bsonDoc); 
collection.Update(Query.EQ("_id",id), updateDoc); 

你的數據庫文件上只對存在於你的jsonString

2

我建議你避免依賴於1.x遺留部分API領域進行更新,如它也完全支持2.x,如下面的示例代碼所示。

var client = new MongoClient(); 
var database = client.GetDatabase("test"); 
var collection = database.GetCollection<BsonDocument>("test"); 

var changesJson = "{ a : 1, b : 2 }"; 
var changesDocument = BsonDocument.Parse(changesJson); 

var filter = Builders<BsonDocument>.Filter.Eq("_id", 1); 

UpdateDefinition<BsonDocument> update = null; 
foreach (var change in changesDocument) 
{ 
    if (update == null) 
    { 
     var builder = Builders<BsonDocument>.Update; 
     update = builder.Set(change.Name, change.Value); 
    } 
    else 
    { 
     update = update.Set(change.Name, change.Value); 
    } 
} 

//following 3 lines are for debugging purposes only 
//var registry = BsonSerializer.SerializerRegistry; 
//var serializer = registry.GetSerializer<BsonDocument>(); 
//var rendered = update.Render(serializer, registry).ToJson(); 

//you can also use the simpler form below if you're OK with bypassing the UpdateDefinitionBuilder (and trust the JSON string to be fully correct) 
update = new BsonDocumentUpdateDefinition<BsonDocument>(new BsonDocument("$set", changesDocument)); 

var result = collection.UpdateOne(filter, update); 

致信Robert Stam提供代碼示例。