2

I have a collection of documents in MongoDB with a structure like this (there are multiple container documents, each containing Sessions, each session contains 1 Order, each Order contains multiple Items):

{
  "Sessions" : [{
      "ID" : "1882a092-d395-45d1-b36b-e2fa3df81b95",
      "Order" : {
        "Items" : [{
            "_id" : "a9c94a5e-10ef-433d-9c63-f4555eb7c2a7",
            "Title" : "UPDATE THIS",
          }]
      }
    }],
  "_id" : "1b640bc4-fdb4-49b1-9c60-e4c6f1bd0405"
}

I would like to update Title of a given Item within an Order in a Session while knowing the _id of the Item (I also know ID of the Session if that helps):

I have tried the following:

col.Update(Query.EQ("Sessions.ID", sessionID),
                Update.Set("Sessions.$.Order.Items.Title", newTitle));

col.Update(Query.EQ("Sessions.Order.Items._id", id),
                Update.Set("Sessions.Order.Items.$.Title", newTitle));

Both throw an exception WriteConcern detected an error 'cannot use the part (Sessions of Sessions.Order.Items.0.Status) to traverse the element .... I also tried different combinations of combined queries using Query.And which probably make so little sense that they are not worth posting here.

How to update field in a subdocument contained in an array of documents using the C# driver?

I realize this cannot be done with the positional operator alone (and the positional operator will not magically match inner array).

I am looking for out of the box solutions how to accomplish this kind of update without changing the schema.

Flexo
  • 87,323
  • 22
  • 191
  • 272
Marek
  • 10,307
  • 8
  • 70
  • 106

2 Answers2

5

Your are not updating sub-document of a sub-document. Your are updating one field of an array's sub-document that is inside the parent array's sub-document.

You can update the first element by the code blow

col.Update(Query.EQ("Sessions.ID", sessionID),
                Update.Set("Sessions.$.Order.Items.0.Title", newTitle));

with a simple update query you cant update all elements' Title. This link might help you (with custom JavaScript update query)

How to multi update of a nested array in MondoDB?

Community
  • 1
  • 1
Disposer
  • 6,201
  • 4
  • 31
  • 38
3

Answer from @Disposer helped me find a solution for this. It spreads multiple areas in my codebase but I would like to share the basic gist with others who may have a similar problem.

These are the steps:

  • Lock the given Order and do not allow items to be added into it (on application level).
  • Alternatively, use a combination of an additional WriteCount field and by using findAndModify to atomically update the document only if it has not been updated in the meantime ("update if current").

Then, when updating Title for a given item:

  • use stored WriteCount
  • determine item index
  • use the item index in combination with the positional operator: $ to identify the session, an integer index to target the item, while employing "update if current" strategy using the WriteCount field.

The update part then becomes:

"Sessions.$.Order.Items." + index + ".Title"
Marek
  • 10,307
  • 8
  • 70
  • 106