9

I have such model:

{  
   "_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",
            }
         ]
      }
   ]
}

I am trying to update value for "key":"testKey2"

I have such update statement:

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

When i try to update for example groupName using such filter ConfigGroup[-1] it works.

But in the case when we have ConfigGroup[-1].Config[-1] it does not work.

I know two options how to update the value:

  • just update whole list using ConfigGroup[-1].Config
  • or specify concrete indexes for filter like ConfigGroup[configGroupIndex].Config[configKeyIndex].Value

But i want to know why it does not work with -1 index. And how to do it properly.

Please answer using c# MongoDB.Driver.

Thanks in advance.

2
  • 1
    I don't believe there is type safe solution. Also using multiple positional operator is only supported from 3.6 mongo version via array filters syntax. Here is one such solution if you are interested. Commented Sep 13, 2018 at 12:11
  • 1
    @Veeram Thx for your comment. So far i didn't find type safe solution Commented Sep 17, 2018 at 14:13

1 Answer 1

14

The reason why it does not work with multiply '-1' because it is the same as positional operator $. In official documentation under the subject of "Nested Arrays" we can see next:

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

From MongoDb 3.6 there are new features that allow to work with nested arrays.

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

So, using the filtered position operator my code looks like this now:

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))
        }
    });
Sign up to request clarification or add additional context in comments.

1 Comment

finally well described answer with example!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.