skip to Main Content

I have collection like this:

mc.db.collection.insert_many([
    {"key_array": [1], "another_array": ["a"]},
    {"key_array": [2, 3], "another_array": ["b"]},
    {"key_array": [4], "another_array": ["c", "d"]},    
])

And I’m using this kind of updates:

mc.db.collection.update_one(
    {"key_array": 5},
    {"$addToSet": {"another_array": "f"}},
    upsert=True
)

It works good with updates, but I have trouble when trying to upsert:
It creates a document with a non-array key_array field, like this

{
    "_id": ObjectId(...)
    "key_array": 5,
    "another_array": ["f"]
}

while I want to have this one

{
    "_id": ObjectId(...)
    "key_array": [5],
    "another_array": ["f"]
}

Also, I cannot use the {"key_array": [5]} style query, because it won’t match the existing array with length > 1.

So, is there any chance to save such behavior on updates, and receive the correct document structure on inserts?

Any help will be appreciated

3

Answers


  1. Chosen as BEST ANSWER

    Ok, finally I had solved this issue with two consecutive updates, the first as specified in the question - upserts with non-array query field, and the second which converts the field to an array if it belongs to another type.

    from pymongo import UpdateOne
    
    bulk = [
        UpdateOne(
            {"key_array": 6},
            {"$addToSet": {"another_array": "e"}},
            upsert=True
        ),
        UpdateOne(
            {
                "$and": [{"key_array": 6},
                         {"key_array": {"$not": {"$type": "array"}}}]
            },
            [{"$set": { "key_array": ["$key_array"]}}]
        )
    ]
    
    mc.db.collection.bulk_write(bulk)
    

    But I'm still looking for a more elegant way to do such a thing.


  2. how about this one.

    db.collection.update({
      "key_array": 5
    },
    {
      "$addToSet": {
        "another_array": "f",
        
      },
      "$set": {
        "key_array": [
          5
        ]
      }
    },
    {
      "upsert": true
    })
    

    https://mongoplayground.net/p/4YdhKuzr2I6

    Login or Signup to reply.
  3. This should help.
    https://www.mongodb.com/docs/manual/reference/operator/update/setOnInsert/

    mc.db.collection.update_one(
        {"key_array": 5},
        {
            "$addToSet": {"another_array": "f"},
            "$setOnInsert": {"key_array": [5], ...}
        },
        upsert=True
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search