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

Upsert querying an array, then pushing to this array with simple values

    XMLWordPrintable

Details

    • Bug
    • Status: Closed
    • Major - P3
    • Resolution: Works as Designed
    • 3.6.4
    • None
    • Write Ops
    • None
    • ALL
    • Hide

      db.empty.update({"list": "value"}, {"$push": {list: "value", {upsert: 1});
      The field 'list' must be an array but is of type string in document {no id}

      db.empty.update({"list": {"$elemMatch": "value", {"$push": {list: "value"}}, {upsert: 1});}}
      $elemMatch needs an Object

      db.empty.update({"list": {"$in": ["value"], {"$push": {list: "value"}}, {upsert: 1});}}
      The field 'list' must be an array but is of type string in document {no id}

      db.empty.update({"list": {$in: ["value", "___wrong"], {"$push": {list: "value"}}, {upsert: 1});}}
      // success

      Show
      db.empty.update({"list": "value"}, {"$push": {list: "value", {upsert: 1}); The field 'list' must be an array but is of type string in document {no id } db.empty.update({"list": {"$elemMatch": "value" , {"$push": {list: "value"}}, {upsert: 1});}} $elemMatch needs an Object db.empty.update({"list": {"$in": ["value"] , {"$push": {list: "value"}}, {upsert: 1});}} The field 'list' must be an array but is of type string in document {no id } db.empty.update({"list": {$in: ["value", "___wrong"] , {"$push": {list: "value"}}, {upsert: 1});}} // success

    Description

      As stated in the docs:

      The update creates the new document with [...] the fields and values of both the <query> and <update> parameters if the <update> parameter contains update operator expressions. The update creates a base document from the equality clauses in the <query> parameter, and then applies the update expressions from the <update> parameter.

       

      So of course, this fails:

      db.empty.update({"list": "value"}, {"$push": {list: "value", {upsert: 1});

      with

      The field 'list' must be an array but is of type string in document {no id}

      The workaround, suggested in https://jira.mongodb.org/browse/SERVER-20203 is to add an $elemMatch to the query, so that the upserted document is not "pre-filled" with a scalar value for the list key.

      But this does not work here: $elemMatch refuses to match single values, so:

      db.empty.update({"list": {"$elemMatch": "value", {"$push": {list: "value"}}, {upsert: 1});}}

      yields

      $elemMatch needs an Object

        

      If I remember correctly, a working workaround used to be:

      db.empty.update({"list": {"$in": ["value"], {"$push": {list: "value"}}, {upsert: 1});}}

      in 3.2 or 3.4 ; but $in with single value arrays are considered equality matches in 3.6 (i'm guessing here), and this last option fails with

      The field 'list' must be an array but is of type string in document {no id}

      again.

      The only way I found to do this is

      db.empty.update({"list": {$in: ["value", "___wrong"], {"$push": {list: "value"}}, {upsert: 1});}}

      but this seems very inefficient and I would like to have a cleaner option

      Attachments

        Issue Links

          Activity

            People

              asya.kamsky@mongodb.com Asya Kamsky
              arthur Arthur Darcet
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: