尝试更新映射值时“更新表达式中提供的文档路径对于更新无效”

Ant*_*ong 10 python amazon-dynamodb

这是我的示例代码

import boto3

import os

ENV = "dev"
DB = "http://awsservice.com"
REGION = "us-east-1"
TABLE = "traffic-count"


def main():
    os.environ["AWS_PROFILE"] = ENV
    client = boto3.resource("dynamodb", endpoint_url=DB, region_name=REGION)

    kwargs = {'Key': {'id': 'D-D0000012345-P-1'}, 
            'UpdateExpression': 'ADD #count.#car  :delta \n            SET #parentKey = :parent_key, #objectKey = :object_key', 
            'ExpressionAttributeValues': {':delta': 1, ':parent_key': 'District-D0000012345', ':object_key': 'Street-1'}, 
            'ExpressionAttributeNames': {'#car': 'car', '#count': 'count', '#parentKey': 'parentKey', '#objectKey': 'objectKey'}}

    client.Table(TABLE).update_item(**kwargs)


if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

我想要实现的是:

通过一次 API 调用(在此update_item),我希望能够

  1. 如果该项目不存在。使用地图创建一个项目count并使用 初始化它{'car': 1}并设置字段parent_keyobject_key

或者

  1. 如果该项已存在,则将该字段更新为{'car': 2}(如果原始计数为 1)

以前,如果我没有使用地图,我可以使用此表达式成功更新,

SET #count = if_not_exist(#count, :zero) +  :delta, 
    #parentKey = :parent_key, #objectKey = :object_key
Run Code Online (Sandbox Code Playgroud)

但是我收到此错误:

botocore.exceptions.ClientError:调用UpdateItem操作时发生错误(ValidationException):更新表达式中提供的文档路径对于更新无效

哪个文档路径导致了问题?我该如何修复它?

Van*_*gaS 12

对于那些登陆此页面并出现类似错误的人:

The document path provided in the update expression is invalid for update
Run Code Online (Sandbox Code Playgroud)

原因可能是:

for the item on which the operation is being performed, 
this attribute (count, for example) is not yet set.
Run Code Online (Sandbox Code Playgroud)

考虑到问题中的示例代码,异常可能来自所有为count空或未设置的项目。因此更新查询不知道map需要设置或更新哪些新值(例如汽车)。

在这个问题中,OP 一开始是可能的,因为属性不是 amap并且过程只是将值设置为count原样。它不会尝试访问未知映射的键来设置值。

这可以通过捕获异常来处理。例如:

from botocore.exceptions import ClientError
...
try:
    response = table.update_item(
        Key={
            "pk": pk
        },
        UpdateExpression="set count.car = :c,
        ExpressionAttributeValues={
            ':c': "some car"
        },
        ReturnValues="UPDATED_NEW"
    )
except ClientError as e:
    if e.response['Error']['Code'] == 'ValidationException':
        response = table.update_item(
            Key={
                "pk": pk
            },
            UpdateExpression="set count = :count",
            ExpressionAttributeValues={
                ':count': {
                    ':c': "some car"
                }
            },
            ReturnValues="UPDATED_NEW"
        )
Run Code Online (Sandbox Code Playgroud)