Patch REST API to Partial Update MongoDB in .NET

谁说我不能喝 提交于 2019-12-09 06:58:24

问题


I have an object

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

I want to send a REST PATCH request to my API to only update one of these properties

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

This gets parsed into a class

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

I now need to update the existing document in MongoDB but only updating the property C.

I could create an update definition just for this one record

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

Or I could hard code a check on each property to see if it is empty

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>));
}

However, if I have many properties and many sub properties this could get very large very fast. The other issue is that if I set the value of the property to be intentionally empty then it would not update the record at all due to it looking for the field to non-empty.

How can I dynamically do partial updates to MongoDB documents in .NET so that I have a generic PATCH API call that can take any of the parameters the document has and only update the properties specified?


回答1:


I suggest that you avoid relying on 1.x legacy API, as it's perfectly supported in 2.x as well, as shown in the sample code below.

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);

Credits go to Robert Stam for providing the code sample.




回答2:


You can use

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

However, you should be careful.

If you first deserialize your document into SomeObject, all of the fields will get their default value (null for strings, 0 for ints etc). And if you use that object for the update, the fields that didn't exist in your json string would be updated to their default value.

If you use

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

your document on the database will be updated only for the fields that are present in your jsonString



来源:https://stackoverflow.com/questions/40526758/patch-rest-api-to-partial-update-mongodb-in-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!