如何使用C#MongoDB.Driver更新深度嵌套的数组?

Ole*_*syk 5 c# mongodb mongodb-.net-driver

我有这样的模型:

{  
   "_id":"5b90eea8c02e062be2888446",
   "storeGuid":"e97d4730-9b8a-49ed-be87-caf4054439aa",
   "storeId":"0",
   "storeDbName":"0",
   "tenant":"dev",
   "configGroup":[  
      {  
         "groupName":"peopleCounter",
         "config":[  
            {  
               "key":"averageWaitPeriodTime",
               "value":"60",
            }
         ]
      },
      {  
         "groupName":"sessionMonitor",
         "config":[  
            {  
               "key":"testKey1",
               "value":"987",
            },
            {  
               "key":"testKey2",
               "value":"123",
            }
         ]
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

我试图更新value"key":"testKey2"

我有这样的更新声明:

await coll.UpdateOneAsync(
    x => x.StoreGuid == storeGuid
         && x.ConfigGroup.Any(y => y.GroupName == groupName
                                   && y.Config.Any(z => z.Key == model.Key)),
    Builders<StoreModel>.Update.Set(x => x.ConfigGroup[-1].Config[-1].Value, model.Value));
Run Code Online (Sandbox Code Playgroud)

例如,当我尝试groupName使用此类过滤器进行更新时,ConfigGroup[-1]它会起作用。

但是在我们拥有的情况下,ConfigGroup[-1].Config[-1]它不起作用。

我知道两个选项如何更新值:

  • 只需使用更新整个列表 ConfigGroup[-1].Config
  • 或为过滤器指定具体索引,例如 ConfigGroup[configGroupIndex].Config[configKeyIndex].Value

但是我想知道为什么它不适用于-1索引。以及如何正确执行。

请使用c#MongoDB.Driver回答。

提前致谢。

Ole*_*syk 6

之所以不能与乘法一起使用'-1',是因为它与位置运算符 相同$。在“嵌套数组”主题下的官方文档中,我们可以看到以下内容:

位置$运算符不能用于遍历一个以上数组的查询,例如遍历嵌套在其他数组中的数组的查询,因为$占位符的替换是单个值

MongoDb 3.6开始,有一些新功能可用于嵌套数组。

全位置运算符

过滤后的位置运算符

过滤后的位置运算符$[<identifier>]标识与arrayFilters条件匹配的数组元素以进行更新操作

因此,使用过滤后的位置运算符,我的代码现在如下所示:

await coll.UpdateOneAsync(x => x.StoreGuid == storeGuid,
    Builders<StoreModel>.Update.Set("configGroup.$[g].config.$[c].value", model.Value),
    new UpdateOptions
    {
        ArrayFilters = new List<ArrayFilterDefinition>
        {
            new BsonDocumentArrayFilterDefinition<BsonDocument>(new BsonDocument("g.groupName", groupName)),
            new BsonDocumentArrayFilterDefinition<BsonDocument>(new BsonDocument("c.key", model.Key))
        }
    });
Run Code Online (Sandbox Code Playgroud)

  • 最后用例子很好地描述了答案! (2认同)