python 未定义文档路径中使用的表达式属性名称;属性名称:买方数量

wsewodh2  于 2023-01-04  发布在  Python
关注(0)|答案(1)|浏览(144)

我正在使用保留DynamoDB关键字live value,users,name。我已经在DynamoDB中创建了一个条目

{
   "id":1
  "poc_name": "ABC"
}

现在,我想使用以下内容更新现有记录

{
    "id": 1,
    "poc_name": "ABC",
    "buyer": {
        "value": "id1",
        "label": "Test"
    }
}

如果您选中我正在使用保留关键字“值”。当我尝试更新记录时,我会得到错误:An expression attribute name used in the document path is not defined; attribute name: #buyer。此处更新不起作用,因为DynamoDB中不存在买方Map,这就是为什么我无法找到文档路径。我使用以下代码片段来处理保留关键字,它将生成以下updateValues、updateExpression、expression_attributes_names

updateValues: {':poc_name': ABC, ':buyer_value': 'id1', ':buyer_label': 'Test'}
updateExpression: ['set ','poc_name = :poc_name,','#buyer.#value = :buyer_value,', 'buyer.label = :buyer_label,']
expression_attributes_names: {'#demand_poc_action': 'demand_poc_action', '#value': 'value', '#buyer': 'buyer'}

代码片段:

for key, value in dictData.items():
        if key in RESERVER_DDB_KEYWORDS or (
            "." in key and key.split(".")[1] in RESERVER_DDB_KEYWORDS
        ):
            key1 = key.replace(".", ".#")
            updateExpression.append(f"#{key1} = :{key.replace('.', '_')},")
            updateValues[f":{key.replace('.', '_')}"] = value
            if "." in key:
                expression_attributes_names[f"#{key.split('.')[0]}"] = key.split(".")[0]
                expression_attributes_names[f"#{key.split('.')[1]}"] = key.split(".")[1]
            else:
                expression_attributes_names[f"#{key}"] = key
        else:
            updateExpression.append(f"{key} = :{key.replace('.', '_')},")
            updateValues[f":{key.replace('.', '_')}"] = value
    
UpdateExpression="".join(updateExpression)[:-1],
ExpressionAttributeValues=updateValues,
ReturnValues="UPDATED_NEW",
ExpressionAttributeNames=expression_attributes_names,

现在的问题是,如果买方已经存在于DynamoDB中,那么我将能够更新买方记录,但是我无法更新买方的记录,因为在DynamoDB中没有买方,那么我会得到文档路径错误。所以我的方法是,我将创建买方的条目,每次我做更新。但是,我无法修复上述代码,请建议我,

mf98qq94

mf98qq941#

发生这种情况是因为您正在尝试更新顶层属性buyer的嵌套属性,该属性尚不存在(OR不是Map类型)
因此,在运行此更新之前,必须确保顶级属性buyer已经存在。
或者,您可以在抛出异常时捕获异常,然后执行另一个更新,创建buyer属性,如下所示:

import boto3
from botocore.exceptions import ClientError

table = boto3.resource('dynamodb', region_name='eu-west-1').Table('test1')

try:
    table.update_item(
        Key={
            'pk': '1'
        },
        UpdateExpression="SET #buyer.#value = :val1, #buyer.#label = :val2",
        ExpressionAttributeNames={
            '#label': 'label',
            '#value': 'value',
            '#buyer': 'buyer',
        },
        ExpressionAttributeValues={
            ':val1': 'id1',
            ':val2': 'Test'
        }
    )
except ClientError as e:
       if e.response['Error']['Code'] == 'ValidationException':
            # Creating new top level attribute `buyer` (with nested props)
            # if the previous query failed
            response = table.update_item(
                Key={
                    'pk': '1'
                },
                UpdateExpression="set #buyer = :val1",
                ExpressionAttributeNames={
                    '#buyer': 'buyer'
                },
                ExpressionAttributeValues={
                    ':val1': {
                        'value': 'id1',
                        'label': 'Test'
                    }
                }
            )
        else:
            raise

另一种方法是在创建项目时简单地将buyer设置为空Map:

{
   "id":1,
   "poc_name": "ABC",
   "buyer": {}
}

这将允许您更新嵌套属性,因为buyer将存在。

相关问题