如何更新 python 中的 DynamoDB 嵌套属性?

How to update DynamoDB nested attribute in python?

我遇到需要更新嵌套 dynamodb 条目中的属性的情况。

下面是我的示例 DynamoDB 条目。

table 具有:pipeline_name 作为分区键,pipeline_run_id 作为排序键.

考虑到我想使用 pipeline_name , pipeline_run_id, name 和 validation_method_results[columnCheck] 作为我的谓词,用另一个字符串值更新我的 validation_method_results 中任何键值对的值。

我的 python 函数会收到如下内容:

update_status(pipeline_name,pipeline_run_id,dependency_name,validation_method,'new_value')

所以我会为它提供这样的输入(这是为了反映我下面的示例):

update_status('demo','demo-2021-04-29T16:48:46.295','dep-demo','columnCheck','new_value')

我在掌握 DynamoDb 中的条件表达式构造时遇到了困难,我们将不胜感激。

{
  "force_run": 0,
  "last_updated_ts": "2021-04-29T16:48:46.295",
  "pipeline_dependencies": [
    {
      "name": "dep-demo", // name 
      "status": "inactive",
      "validation_method_results": [
        {
          "columnCheck": "success" // example key to update with 'new_value' 
        },
        {
          "fileexists": "success" // need to be able to update any of this 
        }
      ]
    },
    {
      "name": "dep-demo-1",
      "status": "active",
      "validation_method_results": [
        {
          "columnCheck": "none" // need to be able to update any of this 
        },
        {
          "fileexists": "none" // need to be able to update any of this 
        },
        {
          "othermethod": "none" // need to be able to update any of this 
        }
      ]
    }
  ],
  "pipeline_name": "demo", // Partition Key 
  "pipeline_run_id": "demo-2021-04-29T16:48:46.295", // Sort Key
  "pipeline_run_status": "pending",
  "pipeline_stage": "dependency_validation"
} 

我为我的用例找到了 answer/solution。

我将 post 放在这里,以防有人想要使用或改进它。

dynamodb 中非常嵌套的属性的问题似乎是找到您想要进行更新的正确数组索引位置。

因此,在触发我的 update_item 语句之前,我不得不做一些额外的工作来找到这些索引。

我创建了这两个简单的函数来帮助我完成这个过程。

    def find_dep_index_location(lst, key, key_value):
        for i, dic in enumerate(lst):
            if dic[key] == key_value:
                return i
        return -1
    
    def find_validation_index_location(lst, key_value):
        for i, dic in enumerate(lst):
            if key_value in list(dic):
                return i
# update function
def update_ed_pipeline_log_runs_validation_status(log_table, pipeline_name, pipeline_run_id, dependency_name,validation_method, validation_method_state):
    session = boto3.session.Session()
    dynamodb = session.resource('dynamodb')
    dynamotable = dynamodb.Table(log_table)

    # i first have to go and fetch this record from dynamodb first
    # this will be used by help function to find the location idx
    run_config = get_runConf(pipeline_name, pipeline_run_id)
    # Start Find nested array list locations
    lst = run_config['pipeline_dependencies']
    key = 'name'
    key_value = dependency_name
    dep_index = find_dep_index_location(lst, key, key_value)

    lst = put_item['pipeline_dependencies'][dep_index]['validation_method_results']
    key_value = validation_method
    method_index = find_validation_index_location(lst, key_value)
    # End Find nested array list locations
    new_status = {key_value : validation_method_state}

    try:
        dynamotable.update_item(
            Key={
                'pipeline_name': pipeline_name,
                'pipeline_run_id': pipeline_run_id
            },
            UpdateExpression="SET #dep[" + str(dep_index) + "].#method[" + str(method_index) + "] = :locVal",
            ExpressionAttributeNames={
                '#dep': 'pipeline_dependencies',
                '#method': 'validation_method_results'
            },
            ExpressionAttributeValues={
                ':locVal': new_status,
            },
        )
    except Exception as e:
        logging.error(' -- ERROR -- ' + str(e))
        raise e

但这同样适用于我的用例,none您可以更改密钥以应用于您自己的用例的次数越少。 这看起来高度未优化,但它确实有效,如果有人有任何想法我可以绕过第一次获取并一步完成我的更新,我将不胜感激。

感谢