【问题标题】:MongoDB Append to Object which is a value for a FieldMongoDB 附加到对象,它是字段的值
【发布时间】:2020-10-12 10:02:05
【问题描述】:

我正在使用 PyMongo 更新集合中的文档。我的文档结构如下所示:

{
    "_id": "123XYZ",
    "location": {
        "date1": [54, 64],
        "date2": [34, 44]
    }
}

我的有效载荷如下所示:

{"date3":[30,40], "date4":[50,60]}

我想更新指定 _id(在本例中为“123XYZ”)的位置字段,使其如下所示:

{
    "_id": "123XYZ",
    "location": {
        "date1": [54, 64],
        "date2": [34, 44],
        "date3": [30,40],
        "date4": [50,60]
    }
}

我一直在搜索文档和堆栈溢出,但找不到简单地附加到该位置的方法。当我尝试将位置更改为数组时,每次尝试附加有效负载只会创建一个额外的嵌套。

我尝试过 $set、$setOnInsert、$addToSet 运算符和其他运算符。我知道有点符号可以让我遍历嵌套对象。但是解压有效载荷并循环遍历密钥并将它们粘贴到点符号上的计算效率很低。所以想知道是否有更好的方法来做到这一点?

有人有想法吗?

【问题讨论】:

  • 你是用updateOne还是别的什么?

标签: mongodb pymongo


【解决方案1】:

使用python合并字典,使用$set操作符。

from pymongo import MongoClient
from pprint import pprint

db =  MongoClient()['mydatabase']

db.mycollection.insert_one({
    "_id": "123XYZ",
    "location": {
        "date1": [54, 64],
        "date2": [34, 44]
    }
})

new_items = {"date3":[30,40], "date4":[50,60]}

filt = {"_id": "123XYZ"}

existing_items = db.mycollection.find_one(filt)

updated_location = {**existing_items.get('location'), **new_items}

db.mycollection.update_one(filt, {'$set': {'location': updated_location}})

pprint(db.mycollection.find_one())

结果:

{'_id': '123XYZ',
 'location': {'date1': [54, 64],
              'date2': [34, 44],
              'date3': [30, 40],
              'date4': [50, 60]}}

【讨论】:

    【解决方案2】:

    使用数组时的替代答案

    $addToSet$each 运算符一起使用会变得更容易。

    from pymongo import MongoClient
    from pprint import pprint
    
    db =  MongoClient()['mydatabase']
    
    db.mycollection.insert_one({
        "_id": "123XYZ",
        "location": [
            {"date1": [54, 64]},
            {"date2": [34, 44]}
        ]
    })
    
    new_items = {"date3":[30,40]}, {"date4":[50,60]}
    
    filt = {"_id": "123XYZ"}
    
    db.mycollection.update_one(filt, {'$addToSet': {'location': {'$each': new_items}}})
    
    pprint(db.mycollection.find_one())
    

    结果:

    {'_id': '123XYZ',
     'location': [{'date1': [54, 64]},
                  {'date2': [34, 44]},
                  {'date3': [30, 40]},
                  {'date4': [50, 60]}]}
    

    【讨论】:

      【解决方案3】:

      我最终这样做了,尽管 Belly Buster 提供了两种方法都有效,但我不想进一步嵌套在数组中,也不想在单个操作中进行读写。我最终像这样遍历每个字典键:

      for item in payload.keys():
          field = "location."+ item #The '.' is crucial here
          payload = {"$set":{field : payload[item}}
          mycol.update_one({"_id": documentID}, payload, upsert=True)
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-28
        • 1970-01-01
        • 1970-01-01
        • 2020-08-14
        • 2011-10-13
        • 2021-06-04
        • 1970-01-01
        相关资源
        最近更新 更多