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

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

    • Type: Icon: Bug Bug
    • Resolution: Works as Designed
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 3.6.4
    • Component/s: Write Ops
    • Labels:
      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

      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

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

              Created:
              Updated:
              Resolved: