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
CodePudding user response:
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
)
CodePudding user response:
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
CodePudding user response:
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.