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

时间:2018-09-13 10:11:42

标签: 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",
            }
         ]
      }
   ]
}

我正在尝试将value的{​​{1}}更新

我有这样的更新声明:

"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)); 更新groupName时,它将起作用。

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

我知道两种更新值的方法:

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

但是我想知道为什么它不适用于ConfigGroup[configGroupIndex].Config[configKeyIndex].Value索引。 以及如何正确执行。

请使用 c#MongoDB.Driver 回答。

谢谢。

1 个答案:

答案 0 :(得分:5)

不能与乘法'-1'一起使用的原因,因为它与positional operator $相同。 在“嵌套数组”主题下的官方文档中,我们可以看到下一个:

  

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

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

The all positional operator

The filtered positional operator

  

过滤后的位置运算符$[<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))
        }
    });