【问题标题】:How can i update to different value in each of nested list如何在每个嵌套列表中更新为不同的值
【发布时间】:2020-12-10 20:48:45
【问题描述】:

所以我收集了以下文档:

{
  "_id": {
    "$oid": "5f3f7a44e9cb27622304f889"
  },
  "date": "21.08.2020",
  "orgPin": "e3jINZgIjhRyY58nLd1lrRz6",
  "process": [
    {
  "periodPin":"u3IpP5Wsq13Woi4dFYET07PX5KDE5V6c",
      "fullStartDate": {
    "$date": "2020-08-21T11:39:48.000Z"
      },
      "checkedBy": "C0D5B93D-A373-4EDF-B5A7-4A58C6EC8C88",
      "workList": [
         {
          "workId": "5f0fff55dc86bc42746ad717",
          "status": 1,
          "description": "",
        },
        {
          "workId": "5f0fff55dc86bc42746ad71a",
          "status": 1,
          "description": "",
        },
        {
          "workId": "5f0fff55dc86bc42746ad71f",
          "status": 1,
          "description": "",
        },
        {
          "workId": "5f0fff55dc86bc42746ad721",
         "status": 1,
          "description": "",
        }
      ]
    }
  ]
}

我在后端(python)中有另一个对象:

{
  '5f0fff55dc86bc42746ad71f': 'Baku',
  '5f0fff55dc86bc42746ad71a': 'Qarachukhur'
}

所以我想将“description”更改为“Baku”,其中“workId”等于“5f0fff55dc86bc42746ad71f”,并将“description”更改为“Qarachukhur”,其中“workId”等于“5f0fff55dc86bc42746ad71a”。 我可以在 python 中循环执行它,但它不适合最佳实践。请帮我在 mongodb 中使用一个查询来解决这个问题。

【问题讨论】:

    标签: python mongodb nosql pymongo


    【解决方案1】:

    bulkWrite() 接受一个写操作数组并执行它们中的每一个。默认情况下,操作是按顺序执行的。

    您有不同的条件来更新文档。正如您所说,在循环中更新(即逐个更新语句)效率不高。

    但是您可以使用bulk write。在后端循环它并准备所有更新语句并以单个批量写入的形式发送。这样做的好处是它是高效的并且减少了网络往返时间。这也是批量写入的目的。

    Refer documentation

    来自 doc 的语法: - 从客户端的角度向服务器查询。

    db.collection.bulkWrite( [
       { updateOne :
          {
             "filter": <document>,
             "update": <document or pipeline>,            // Changed in 4.2
             "upsert": <boolean>,
             "collation": <document>,                     // Available starting in 3.4
             "arrayFilters": [ <filterdocument1>, ... ],  // Available starting in 3.6
             "hint": <document|string>                    // Available starting in 4.2.1
          }
       }
    ] )
    

    您可以有多个updateOne 语句。不仅updateOne,还有很多update operators,即更新、替换..

    【讨论】:

    • 嗨,我的朋友,谢谢你,我明白了这个bulkWrite。但是如何将 array_filter -参数与 bulkWrite 一起使用?在 pymongo 中
    • 它有一个选项。请参考语法。
    【解决方案2】:

    我找到了问题的解决方案

    之前我想说点什么:
    在这个例子中,我将分享我的部分 Web API(这是我们需要的),并且我需要来自前端开发人员的一些数据。数据是这样的:
    {
      "orgPin": "e3jINZgIjhRyY58nLd1lrRz6",
      "periodPin": "u3IpP5Wsq13Woi4dFYET07PX5KDE5V6c",
      "doneWorkList": [
        {
          "workId": "5f0fff55dc86bc42746ad717",
          "status": 2
        },
        {
          "workId": "5f0fff55dc86bc42746ad71f",
          "status": 1
        },
        {
          "workId": "5f0fff55dc86bc42746ad71a",
          "status": 4,
          "description": "FRFR"
        }
      ]
    }
    

    然后我需要在"workId" 的帮助下更新一些"status" 值。我还将"description" 参数添加到相应的对象中。

    我们能做什么?

    首先,您必须为此查询创建列表,然后将列表粘贴到bulkWrite。在我的示例中,我使用 pymongo 工具。在pymongobulkWrite 中使用bulk_write,在里面我们将使用pymongoUpdateOne 工具。首先我们必须导入pymongoUpdateOne(我们还需要导入MongoClient来连接数据库):

    import pymongo,
    from pymongo import UpdateOne, MongoClient
    

    然后我们需要连接到数据库:

    client = MongoClient('localhost', 27017)
    db = client.test_database
    

    所以,现在我们需要连接到集合:

    collection = db.test_collection
    

    现在我们在重要的问题上。我们必须为我们创建一个列表查询的方法:

    def bulk_write_query(search, work_id, status, interval_pin, description=None):
    update_query = {
        'process.$[arg1].workList.$[arg2].status': status
    }
    if description is not None:
        update_query.update({'process.$[arg1].workList.$[arg2].description': description})
    array_filters_list = [
        {"arg1.periodPin": interval_pin},
        {"arg2.workId": work_id}
    ]
    
    big_query = UpdateOne(
        search,
        {'$set': update_query},
        upsert=False,
        array_filters=array_filters_list
    )
    return big_query
    

    我们需要在主代码位置添加一些变量:

    search_event = {
                      "date": "21.08.2020",
                      "orgPin": "e3jINZgIjhRyY58nLd1lrRz6"
                    }
     interval_pin = "u3IpP5Wsq13Woi4dFYET07PX5KDE5V6c"
    

    最后是我们代码的重要部分:

    query_list = list(map(lambda x: bulk_write_query(search_daily, x['workId'], x['status'], interval_pin) if 'description' not in x else bulk_write_query(search_daily, x['workId'], x['status'], interval_pin, x['description']) or x, done_work_list))
    
    result = collection.bulk_write(query_list)
    print(result.bulk_api_result)
    

    到此结束!我在最后用result.bulk_api_result 打印了处理结果。祝你工作愉快!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-14
      • 2021-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多