补丁REST API到部分更新的MongoDB在.NET

补丁REST API到部分更新的MongoDB在.NET

问题描述:

我有一个对象补丁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调用,可以采取任何文档具有参数,只有指定的属性更新?

您可以使用

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

我建议你避免依赖于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提供代码示例。