如何在不丢失现有未引用字段的情况下向上插入mongodb嵌套对象

时间:2019-07-17 16:49:23

标签: c# mongodb

我在点网中使用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丢失了。

2 个答案:

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

是的,就是这么简单。正如我在问题中所说的那样,我以为我需要解决这个问题,并逐行比较该对象的属性和更新对象的属性,以完成所需的工作。可能是我不熟悉的某种魔术方法。