【问题标题】:C# MongoDB - How to add and remove item to multiple nested array elements?C# MongoDB - 如何向多个嵌套数组元素添加和删除项目?
【发布时间】:2017-12-28 15:16:17
【问题描述】:

我在 MongoDB 中有一个类似这样的文档:

{
    "Id":"123",
    "Product": "test",
    "Tags":[
        {
            "Name": "name",
            "Categories": [
                {
                    //item
                },
                {
                    //item
                }
            ]
        },
        {
            "Name": "name",
            "Categories": [
                {
                    //item
                },
                {
                    //item
                }
            ]
        }
    ]
}

现在,我需要添加一个新的Item,它需要通过其Id 添加到该ProductTags 元素的所有类别中。 例如,当我插入 Item 3 时,文档应如下所示:

{
    "Id":"123",
    "Product": "test",
    "Tags":[
        {
            "Name": "name",
            "Categories": [
                {
                    //item 1
                },
                {
                    //item 2
                },
                {
                    //item 3
                }
            ]
        },
        {
            "Name": "name",
            "Categories": [
                {
                    //item 1
                },
                {
                    //item 2
                },
                {
                    //item 3
                }
            ]
        }
    ]
}

删除一个项目也是如此,它也需要从所有类别中删除。 有没有办法用 C# MongoDB 驱动程序做到这一点,而无需拉取对象并“手动”更新它们?

【问题讨论】:

    标签: c# mongodb mongodb-.net-driver


    【解决方案1】:

    您可以在 3.6 版本的 2.5 驱动程序中尝试以下类似的操作。

    查找具有filter 条件和update 的文档,其中包括新的positional identifier 以更新UpdateOne 方法内数组中的多个元素。

    $[] 更新所有Tags 数组以在所有Categories 数组中包含新项目。它充当一个占位符,用于更新数组中的所有元素。

    var filter = Builders<Product>.Filter.Eq("Id", "123");
    var update = Builders<Product>.Update.Push("Tags.$[].Categories", "Item 3");
    var result = collection.UpdateOne(filter, update);
    

    var filter = Builders<Product>.Filter.Eq("Id", "123");
    var update = Builders<Product>.Update.Pull("Tags.$[].Categories", "Item 3");
    var result = collection.UpdateOne(filter, update);
    

    附加信息:

    您可以在UpdateOptions 中设置ArrayFilters 选项,以便对嵌套数组应用查询条件来控制要更新的元素。

    例如更新标签数组中的所有类别,其中每个标签都有Name 名称。

    var filter = Builders<Product>.Filter.Eq("Id", "123");
    var update = Builders<Product>.Update.Push("Tags.$[t].Categories", "Item 3");
    var arrayFilters = new List<ArrayFilterDefinition>{ new ArrayFilterDefinition(new BsonDocument("t.Name", "name")) };
    var updateOptions = new UpdateOptions({ArrayFilters = arrayFilters});
    var result = collection.UpdateOne(filter, update, updateOptions);
    

    【讨论】:

    • 我在Push 解决方案中遇到此错误:"A write operation resulted in an error.\r\n cannot use the part (Tags of Tags.$[].Categories) to traverse the element
    • 您好像不是最新的 3.6 版本。在shell中执行db.version()查看版本。
    • 我已经检查过了,版本 3.6.1...我在 Robo mongo 中运行它。
    • 没有机会测试 c# 代码,但我能够在 shell 中针对提供的示例数据运行查询。不确定错误在哪里。尝试查看您尝试更新的数据并在 shell 中运行查询。可能是您的某些文档缺少类别或标签,并且两者都是数组类型。在 shell 中尝试db.collection_name.find({"Id":"123"}, {"$push":{"Tags.$[].Categories":"Item 3"}});
    • 我将您的查询复制粘贴到我的 Robo Mongo 查询编辑器中,它给出了这个错误:Error: error: { "ok" : 0, "errmsg" : "Unsupported projection option: $push: { Tags.$[].Categories: \"Item 3\" }", "code" : 2, "codeName" : "BadValue" }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多