我有一份文件,例如
{
"_id": "ABC",
"name": "Bob",
"age": 42
}
我有两个在不同时间分开运行的功能。功能A更新名称和功能B更新年龄。这两个函数都调用外部休息服务,该服务根据服务返回名称或年龄。
我有一个映射到mongo文档的类
public class Person {
[BsonId]
public string Id { get; set; }
[BsonElement("name")]
public string Name { get; set; }
[BsonElement("age")]
public int Age { get; set; }
}
函数A将仅填充此类的Id和Name属性,而函数B将填充Id和Age属性。
如何通过从函数B传递Person对象来更新mongo文档,以便它保留函数A的现有值?
我知道你可以做Builders<Person>.Update.Set(x => x.Age, <new_age>)
但是我希望我的代码更加动态,所以如果我添加另一个名为'Phone'的字段,我可以调用一个只更新字段的泛型方法一个值,不是null。
答案 0 :(得分:0)
仅将要更新的元素添加到新的BsonDocument中,以创建更新定义。
private static void SetUpdatableElements(BsonDocument bdoc, BsonDocument updateDefintion, HashSet<string>() excluded = null, string parentName = "")
{
var excluded = excluded ?? new HashSet<string>()
parentName = !string.IsNullOrWhiteSpace(parentName) ? $"{parentName}." : "";
foreach (var item in bdoc)
{
if (item.Value.IsObjectId || // skip _id
item.Value.IsBsonNull || // skip properties with null values
excluded.Contains(item.Name)) // skip other properties that should not be updated
{
continue;
}
if (!item.Value.IsBsonDocument) // to avoid override nested objects)
{
updateDefintion = updateDefintion.Add($"{parentName}{item.Name}", item.Value);
continue;
}
// recursively set nested elements to avoid overriding the full object
SetUpdatableElements(item.Value.ToBsonDocument(), updateDefintion, item.Name);
}
}
来电者:
var person = new Person() { Id = "ABC", Name = "bob", Age:42, Phone="123 456 7890"}
var updateDefintion = new BsonDocument();
var bDoc = person.ToBsonDocument();
SetUpdatableElements(person.ToBsonDocument(), updateDefintion, new HashSet<string>(nameof(person.Name)))
collection.UpdateOneAsync<Person>(p => p.Id == person.Id, new BsonDocument("$set", updateDefintion));
最后,您的updateDefinition应该类似于:
{ {
"$set": {
"age": 42
"phone": "123 456 7890"
}
} }