MongoDB:带有数组过滤器的UPSERT

发布于 2025-01-18 14:15:14 字数 890 浏览 1 评论 0 原文

我有这样的收藏:

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
)

它可以在更新中效果很好,但是在尝试上升时我遇到了麻烦: 它创建一个使用非阵列 key_array 字段的文档,

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

而我也想拥有一个文档

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

,我也不能使用 {“ key_array”:[5]} 样式查询,因为它与现有数组与长度> 1。

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

任何帮助将不胜感激

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你好,陌生人 2025-01-25 14:15:14

这应该有帮助。

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

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
)
漆黑的白昼 2025-01-25 14:15:14

怎么样。

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

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

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

巷雨优美回忆 2025-01-25 14:15:14

好的,最后,我已经通过两个连续的更新解决了这个问题,该问题是问题中指定的第一个更新 - 具有非阵列查询字段的UPSERTS,第二个将字段转换为数组(如果属于其他类型)。

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)

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文