补丁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提供代码示例。