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

How to update deeply nested array with C# MongoDB.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",
            }
         ]
      }
   ]
}

我正在尝试为 "key":"testKey2"

更新 value

我有这样的更新声明:

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));

当我尝试使用这样的过滤器 ConfigGroup[-1] 更新 groupName 时,它起作用了。

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

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

但我想知道为什么它不适用于 -1 索引。 以及如何正确地做到这一点。

请使用c#MongoDB.Driver.

回答

提前致谢。

之所以不能和乘法'-1'一起工作是因为它和positional operator$是一样的。 在"Nested Arrays"主题下的官方文档中我们可以看到下一个:

The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value

MongoDb 3.6 开始,有允许使用嵌套数组的新功能。

The all positional operator

The filtered positional operator:

The filtered positional operator $[<identifier>] identifies the array elements that match the arrayFilters conditions for an update operation

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

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