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:

          My collection is as follows:

          {
          "_id" : ObjectId("579f05e415d47c452d6d4707"),
          "moduleId" : ObjectId("579f05e415d47c452d6d4706"),
          "canDelete" : true,
          "sections" : [
          {
          "sectionId" : ObjectId("57973f9b7c516c2b44209d4f"),
          "_id" : ObjectId("579f05e415d47c452d6d4713"),
          "skills" : [

          { "skillId" : ObjectId("57973fca7c516c2b44209d5b"), "_id" : ObjectId("579740267c516c2b4420a090"), "Videos" : [ ObjectId("57973ff97c516c2b44209fb3"), *_ ObjectId("591d40bc3162bc4012ebd1c6")_* ], "Questions" : [ ObjectId("57973fe77c516c2b44209dbf"), ObjectId("57973fe77c516c2b44209dc0"), ObjectId("57973fe77c516c2b44209dc1"), ObjectId("57973fe77c516c2b44209dc2"), ObjectId("57973fe77c516c2b44209dc3") ] }

          ,

          { "skillId" : ObjectId("57973fca7c516c2b44209d5c"), "_id" : ObjectId("579740267c516c2b4420a08f"), "Videos" : [ ObjectId("57973ff97c516c2b44209fb4") ], "Questions" : [ ObjectId("57973fe77c516c2b44209dc4"), ObjectId("57973fe77c516c2b44209dc5"), ObjectId("57973fe77c516c2b44209dc6"), ObjectId("57973fe77c516c2b44209dc7"), ObjectId("57973fe77c516c2b44209dc8") ] }

          ]
          }
          ]
          }

          I need to remove ObjectId("591d40bc3162bc4012ebd1c6") from Section ---> Skills --> Video array

          Show
          ketannaik Ketan K Naik added a comment - @Yannick Betemps: My collection is as follows: { "_id" : ObjectId("579f05e415d47c452d6d4707"), "moduleId" : ObjectId("579f05e415d47c452d6d4706"), "canDelete" : true, "sections" : [ { "sectionId" : ObjectId("57973f9b7c516c2b44209d4f"), "_id" : ObjectId("579f05e415d47c452d6d4713"), "skills" : [ { "skillId" : ObjectId("57973fca7c516c2b44209d5b"), "_id" : ObjectId("579740267c516c2b4420a090"), "Videos" : [ ObjectId("57973ff97c516c2b44209fb3"), *_ ObjectId("591d40bc3162bc4012ebd1c6")_* ], "Questions" : [ ObjectId("57973fe77c516c2b44209dbf"), ObjectId("57973fe77c516c2b44209dc0"), ObjectId("57973fe77c516c2b44209dc1"), ObjectId("57973fe77c516c2b44209dc2"), ObjectId("57973fe77c516c2b44209dc3") ] } , { "skillId" : ObjectId("57973fca7c516c2b44209d5c"), "_id" : ObjectId("579740267c516c2b4420a08f"), "Videos" : [ ObjectId("57973ff97c516c2b44209fb4") ], "Questions" : [ ObjectId("57973fe77c516c2b44209dc4"), ObjectId("57973fe77c516c2b44209dc5"), ObjectId("57973fe77c516c2b44209dc6"), ObjectId("57973fe77c516c2b44209dc7"), ObjectId("57973fe77c516c2b44209dc8") ] } ] } ] } I need to remove ObjectId("591d40bc3162bc4012ebd1c6") from Section ---> Skills --> Video array
          Hide
          Arkhee Yannick Bétemps added a comment -

          @Ketan
          Not sure since it's not an object and in subsub array, I would try :

          db.mycollection.update({'sections.skills':{$elemMatch:

          {'Videos':ObjectId("57973ff97c516c2b44209fb3")}

          }},
          { $pull: { "sections.$.skills.$.Videos": ObjectId("57973ff97c516c2b44209fb3")}}

          {upsert:false,multi:false}

          // change only one found value
          );
          maybe try to create Videos as one-property object ?
          $pull allows to remove a specific item in an array, whereas the $elemMatch allows to target the right node (since the video may be in other skills or sections), as I understand it

          playing with dots and $ ... this is more of an experimental research here ... work on dev collection

          Show
          Arkhee Yannick Bétemps added a comment - @Ketan Not sure since it's not an object and in subsub array, I would try : db.mycollection.update({'sections.skills':{$elemMatch: {'Videos':ObjectId("57973ff97c516c2b44209fb3")} }}, { $pull: { "sections.$.skills.$.Videos": ObjectId("57973ff97c516c2b44209fb3")}} {upsert:false,multi:false} // change only one found value ); maybe try to create Videos as one-property object ? $pull allows to remove a specific item in an array, whereas the $elemMatch allows to target the right node (since the video may be in other skills or sections), as I understand it playing with dots and $ ... this is more of an experimental research here ... work on dev collection
          Hide
          ketannaik Ketan K Naik added a comment - - edited

          @Yannick Betemps:
          You understood it properly.
          Multiple Positional operators are not supported in MongoDB yet.
          so 2 $ sign in a sign query wont work

          Show
          ketannaik Ketan K Naik added a comment - - edited @Yannick Betemps: You understood it properly. Multiple Positional operators are not supported in MongoDB yet. so 2 $ sign in a sign query wont work
          Hide
          Arkhee Yannick Bétemps added a comment -

          Have you tried using only one $ : the one of the $elemMatch subarray ?

          Show
          Arkhee Yannick Bétemps added a comment - Have you tried using only one $ : the one of the $elemMatch subarray ?
          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

            People

            • Votes:
              344 Vote for this issue
              Watchers:
              271 Start watching this issue

              Dates

              • Created:
                Updated: