【问题标题】:C# mongodb - how to update nested array elementsC# mongodb - 如何更新嵌套数组元素
【发布时间】:2018-02-19 14:26:03
【问题描述】:

我有以下表示项目的 JSON 结构

{
    Id: "a",
    Array1: [{
        Id: "b",
        Array2: [{
            Id: "c",
            Array3: [
                {...}
            ]
        }]
    }]
}

我需要能够将 Array2 中的数组元素替换为新项目,或者仅将 Array3 替换为新数组。

这是我替换Array2中的数组项的代码:

await Collection.UpdateOneAsync(
    item => item.Id.Equals("a") &&
    item.Array1.Any(a => a.Id.Equals("b")) &&
    item.Array1[-1].Array2.Any(b => b.Id.Equals("c")),
    Builders<Item>.Update.Set(s => s.Array1[-1].Array2[-1], newArray2Item)
);

执行此代码时出现此错误:

"A write operation resulted in an error.
 Too many positional (i.e. '$') elements found in path 'Array1.$.Array2.$'"

这是我在Array2 中替换Array3 的代码:

await Collection.UpdateOneAsync(
        item => item.Id.Equals("a") &&
        item.Array1.Any(a => a.Id.Equals("b")) &&
        item.Array1[-1].Array2.Any(b => b.Id.Equals("c")),
        Builders<Item>.Update.Set(s => s.Array1[-1].Array2[-1].Array3, newArray3)
    );

这是错误:

"A write operation resulted in an error.
 Too many positional (i.e. '$') elements found in path 'Array1.$.Array2.$.Array3'"

我正在使用 C# MongoDB 驱动程序版本 2.5.0 和 MongoDB 版本 3.6.1

我发现这张 Jira 票 Positional Operator Matching Nested Arrays 说问题已得到解决,他们建议使用此语法进行更新

Update all matching documents in nested array:

db.coll.update({}, {$set: {“a.$[i].c.$[j].d”: 2}}, {arrayFilters: [{“i.b”: 0}, {“j.d”: 0}]})
Input: {a: [{b: 0, c: [{d: 0}, {d: 1}]}, {b: 1, c: [{d: 0}, {d: 1}]}]}
Output: {a: [{b: 0, c: [{d: 2}, {d: 1}]}, {b: 1, c: [{d: 0}, {d: 1}]}]}

所以我将它转换为我的元素:

db.getCollection('Items').update(
{"Id": "a"},
{$set: {"Array1.$[i].Array2.$[j].Array3": [newArray3]}}, 
{arrayFilters: 
    [
        {"i.Id": "b"}, 
        {"j.Id": "c"}
    ]}
)

得到了这个错误:

cannot use the part (Array1 of Array.$[i].Array2.$[j].Array3) to traverse the element

关于如何解决此错误的任何想法?

【问题讨论】:

  • 它并不漂亮,但作为一种快捷方式,您始终可以使用字符串编写更新,就像在 shell 中编写它们一样,然后将它们传递给 Update() 方法。
  • 这就是我从 Jira 提供样本的原因。还是不行,,,
  • 你需要一个更新的客户端才能工作(试试你的发行版附带的“mongo.exe”shell):stackoverflow.com/questions/47225822/…
  • 我不能在 C# 中使用mongo.exe...你发给我的链接是在谈论 robomongo。
  • 我知道。 ;) 您在示例中给出的最后一个查询是一个基于字符串的查询,您应该能够在 mongo.exe 中运行而不会出现错误。这就是我要说的。一旦你的查询工作正常,你就可以使用过滤器并更新它的一部分来创建一个 C# 版本。

标签: mongodb mongodb-.net-driver


【解决方案1】:

这是您需要的 C# 版本:

var filter = Builders<Item>.Filter.Eq("Id", "a");
var update = Builders<Item>.Update.Set("Array1.$[i].Array2.$[j].Array3", new[] { new Item { Id = "d" } });
var arrayFilters = new List<ArrayFilterDefinition> { new JsonArrayFilterDefinition<Item>("{'i.Id': 'b'}"), new JsonArrayFilterDefinition<Item>("{'j.Id': 'c'}") };
var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };
collection.UpdateOne(filter, update, updateOptions);

【讨论】:

  • 它在 C# 中不起作用,但在 Studio 3T 中起作用,知道为什么吗?它没有给出错误并且看起来命令通过了,但更新不适用......
  • 我看到的唯一区别是我使用 id 的过滤器,如下所示:"_id", "ObjectId(ITEM_ID)" 和这样:"{\"i._id\": ObjectId(ARRAY_ITEM_ID)}"因为 id 由 mongo 生成并由ObjectId 表示。有什么建议吗?
  • 我建议您记录您的查询 (db.setProfilingLevel(2)) 并检查 MongoDB 日志文件,了解运行 C# 代码时生成的查询的样子。我猜,仅此一项就可能揭示问题所在。否则,您可以在 Studio3T 中运行生成的查询,看看它是否在那里产生正确的结果(它不会)以及为什么不产生。
  • mkyong.com/mongodb/mongodb-where-is-the-log-file 用于 Linux 的描述,但也非常适用于 Windows。
  • 我在C:\data\log\mongod.log 下找到了一些日志文件,但它没有向其中写入任何内容...我找不到任何类似于/var/log/mongodb/mongodb.log 的内容
猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 2020-03-16
  • 2020-09-15
  • 1970-01-01
  • 2022-06-11
  • 2022-11-02
  • 2019-06-08
  • 2018-10-06
相关资源
最近更新 更多