MongoDB: 使用数组过滤器更新插入

MongoDB: Upsert with array filter

我有 collection 这样的:

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"]},    
])

我正在使用这种更新:

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

它适用于更新,但我在尝试更新时遇到问题: 它创建一个带有 non-array key_array 字段的文档,像这样

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

虽然我想要这个

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

此外,我无法使用 {"key_array": [5]} 样式查询,因为它不会匹配长度 > 1 的现有数组。

那么,是否有机会在更新时保存此类行为,并在插入时接收正确的文档结构?

任何帮助将不胜感激

这个怎么样。

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

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

好吧,最后我通过两次连续更新解决了这个问题,第一个是问题中指定的 - 使用 non-array 查询字段更新,第二个将字段转换为数组,如果它属于另一种。

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)

但我仍在寻找一种更优雅的方式来做这样的事情。

这应该有所帮助。 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
)