Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-831

Positional Operator Matching Nested Arrays

    Details

      Description

      Issue Status as of Dec 06, 2016

      We recognize that this feature is highly requested by the community; we are investigating implementation approaches and considering designs for the required query language extensions in SERVER-27089. We appreciate the challenge of maintaining applications with schemas including large arrays, and the work described in SERVER-27089 includes this feature request as well as other related improvements to array update capabilities. Please feel free to review SERVER-27089 for additional details around the requirements of this work and watch it for updates.

      Original Description

      For cases where arrays can be nested within other arrays multiple levels deep, it would be great if the positional operator could match the appropriate array no matter how far deep the nesting goes. A syntax for this could be something like:

      collection.update(
        { "_id" : 1, "medications._id" : 23, "medications.prescriptions._id" : 77 },
        { $set : { "medications.$0.prescriptions.$1.quantity" : 30 } },
        false,
        true
      )
      

      Here is a link to a gist with a sample document. In our current application we actually nest as many as 5 levels deep and some cases, and would like to be able to do atomic updates on fields at the very bottom of the tree for efficiency.

      http://gist.github.com/342738

        Issue Links

          Activity

          Hide
          ketannaik Ketan K Naik added a comment -

          @Yannick Betemps: Unfortunately even that does not work

          Show
          ketannaik Ketan K Naik added a comment - @Yannick Betemps: Unfortunately even that does not work
          Hide
          katakam.maniratnam@gmail.com Maniratnam Katakam added a comment -

          Hello All,

          I have a similar situation I guess, the following is the sample Json document in which I need to query on.

          {
          "_id" : ObjectId("591d601fc9f360331cd4668c"),
          "Type" : "district",
          "GroupId" : "00000000-0000-0000-0000-000000000456",
          "Grades" : [
          {
          "GroupId" : "gs00000000-0000-0000-0000-000000000452",
          "Categories" : [

          { "Sequence" : 1, "Low" : 0, "High" : 99, "Min" : 0, "Max" : 0, }

          ,

          { "Sequence" : 1, "Low" : 50, "High" : 99, "Min" : 0, "Max" : 0, }

          ]
          }
          ],
          "NumberOfTypes" : 4,
          "CreatedDate" : ISODate("2017-05-18T08:49:35.433Z"),
          "LastModifiedDate" : ISODate("2017-05-26T16:12:52.093Z"),
          "Status" : true
          }

          I need to pick all the document where the value of "Low": 0 and change to 1. I am trying the following query

          db.BenchmarkDetails.update(

          {"Grades.Categories.Low" : 0}

          ,
          {$set :

          {"Grades.Categories.$.Low" : 1}

          }
          )

          This throwing the error

          cannot use the part (Grades of Grades.Categories.0.Low) to traverse the element.

          Show
          katakam.maniratnam@gmail.com Maniratnam Katakam added a comment - Hello All, I have a similar situation I guess, the following is the sample Json document in which I need to query on. { "_id" : ObjectId("591d601fc9f360331cd4668c"), "Type" : "district", "GroupId" : "00000000-0000-0000-0000-000000000456", "Grades" : [ { "GroupId" : "gs00000000-0000-0000-0000-000000000452", "Categories" : [ { "Sequence" : 1, "Low" : 0, "High" : 99, "Min" : 0, "Max" : 0, } , { "Sequence" : 1, "Low" : 50, "High" : 99, "Min" : 0, "Max" : 0, } ] } ], "NumberOfTypes" : 4, "CreatedDate" : ISODate("2017-05-18T08:49:35.433Z"), "LastModifiedDate" : ISODate("2017-05-26T16:12:52.093Z"), "Status" : true } I need to pick all the document where the value of "Low": 0 and change to 1. I am trying the following query db.BenchmarkDetails.update( {"Grades.Categories.Low" : 0} , {$set : {"Grades.Categories.$.Low" : 1} } ) This throwing the error cannot use the part (Grades of Grades.Categories.0.Low) to traverse the element.
          Hide
          asya Asya Kamsky added a comment - - edited

          Hi all,

          We are currently making progress on a solution to this issue under SERVER-27089. Since this feature is still in development, and not yet switched on in a development release, we don't yet have documentation for how it will work. But to give you a quick preview, you will be able to update values and subdocuments inside nested array(s) as follows:

          db.coll.update({}, {$set: {"a.$[i].b.$[j].c": 5}},  {arrayFilters: [{"i.id": 1},{"j.c":1]});
           
          Input: {a: [{id:1, b: [{c: 0},{c:1}]]}
          Output: {a: [{id:1, b: {[c:0},{c:5}]]}
          

          We will post a more formal update on SERVER-27089 when this work is complete.

          Best,
          Asya

          Show
          asya Asya Kamsky added a comment - - edited Hi all, We are currently making progress on a solution to this issue under SERVER-27089 . Since this feature is still in development, and not yet switched on in a development release, we don't yet have documentation for how it will work. But to give you a quick preview, you will be able to update values and subdocuments inside nested array(s) as follows: db.coll.update({}, {$set: {"a.$[i].b.$[j].c": 5}}, {arrayFilters: [{"i.id": 1},{"j.c":1]}); Input: {a: [{id:1, b: [{c: 0},{c:1}]]} Output: {a: [{id:1, b: {[c:0},{c:5}]]} We will post a more formal update on SERVER-27089 when this work is complete. Best, Asya
          Hide
          murilolobatto Murilo Lobato added a comment -

          This is great news! I'm really dependent of this feature.

          Show
          murilolobatto Murilo Lobato added a comment - This is great news! I'm really dependent of this feature.
          Hide
          amcgregor Alice Bevan-McGregor added a comment - - edited

          A solution: awesome. Looking forward to it. Curious syntax, though. Named references are cool, but why the braces? Are $name references within a longer field reference currently reserved? E.g. {$set: {"a.$i.b.$j.c": 5}} (edge case: {$set: {"$i": 5}}) AFIK $ is not allowed in saved field names. It just seems a strange departure from otherwise minimal "glue" syntax.

          Show
          amcgregor Alice Bevan-McGregor added a comment - - edited A solution: awesome. Looking forward to it. Curious syntax, though. Named references are cool, but why the braces? Are $name references within a longer field reference currently reserved? E.g. { $set: {"a.$i.b.$j.c": 5 }} (edge case: { $set: {"$i": 5 }}) AFIK $ is not allowed in saved field names. It just seems a strange departure from otherwise minimal "glue" syntax.

            People

            • Votes:
              350 Vote for this issue
              Watchers:
              280 Start watching this issue

              Dates

              • Created:
                Updated: