我在点网中使用C#在mongodb中创建和更新简单集合(我是nosql的新手,只做过mysql)。创建是没有问题的,而且更新在很大程度上也没有问题。但是我有一个嵌套的对象,它在更新时可能会包含现有字段。如果请求不使用这些字段,则只会添加引用的字段,即要插入或更新的字段,而现有的字段会丢失。
在此处搜索了类似的问题,但没有找到完全匹配的内容。一些对方法AddToSet和AddToSetEach的引用,但在这里认为它们不太合适。
发现提到首先获取现有文档并对其进行更新,但认为这可能会变得混乱,并且这必须是直接解决方案的常见问题。
更新g(经删节)的代码非常简单:
public class Issue {
public string Id { get; set; }
public IDictionary<string, string> Properties { get; set; }
public string AssignedToUserId { get; set; }
}
var issue = new Issue {
Id = "MEC0eNrSQk2ZhDJnZ3f36g",
AssignedToUserId = "someuserid",
Properties = new Dictionary<string, string>
{
{ "prop2", "ghj" },
{ "prop3", "xyz" }
};
}
var update = Builders<Issue>.Update
.Set(x => x.AssignedToUserId, issue.AssignedToUserId)
.Set(x => x.Properties, issue.Properties);
await _mongoDb.UpdateOneAsync(Builders<Issue>.Filter.Eq(x => x.Id, issue.Id), update);
Document on creation (abridged):
{
"_id" : "MEC0eNrSQk2ZhDJnZ3f36g",
"Properties" : {
"prop1" : "abc",
"prop2" : "def"
},
"AssignedToUserId" : null
}
我希望通过以下方式更新属性对象:
将prop2
的值更改为ghj
添加具有一些任意值的新字段prop3
[让prop1离开地狱!]
结果(仅显示属性对象)
"Properties" : {
"prop2" : "ghj"
"prop3" : "xyz"
}
因此添加了新属性,我想更改的现有属性已确定,但是prop1
丢失了。
答案 0 :(得分:1)
您需要使用$set
运算符发出更新命令。您的道具可以使用点缀路径来指定目标名称,如下所示:
db.Issue.update({
"_id": ObjectId("5d2fd8e820f6a5274823cbee")
}, {
"$set": {
"Properties.prop2": "geh",
"Properties.prop3": "xyz"
}
})
这是生成上述查询的C#代码。为了简便起见,它使用的是我的MongoDB.Entities库。
using MongoDB.Entities;
using System.Collections.Generic;
namespace StackOverflow
{
public class Program
{
public class Issue : Entity
{
public IDictionary<string, string> Properties { get; set; }
}
private static void Main(string[] args)
{
new DB("test");
var issue = new Issue
{
Properties = new Dictionary<string, string>
{
{ "prop1", "abc" },
{ "prop2", "def" }
}
};
issue.Save();
DB.Update<Issue>()
.Match(i => i.ID == issue.ID)
.Modify(i => i.Properties["prop2"], "geh")
.Modify(i => i.Properties["prop3"], "xyz")
.Execute();
}
}
}
答案 1 :(得分:0)
我可能不应该回答我自己的问题,但是当我最终提出解决方案时,由于它非常简单,我将其发布(我还将向Ryan Gunner表示接受,因为我会解释原因。在评论他的答案中。)
//update = update.Set(x => x.Properties, issue.Properties)
foreach (var props in issue.Properties)
{
update = update.Set(x => x.Properties[props.Key], props.Value);
}
是的,就是这么简单。正如我在问题中所说的那样,我以为我需要解决这个问题,并逐行比较该对象的属性和更新对象的属性,以完成所需的工作。可能是我不熟悉的某种魔术方法。