当嵌套路径不存在时 DynamoDB 更新失败

Hay*_*ate 6 javascript amazon-dynamodb dynamodb-queries documentclient

我的表结构如下,其中time唯一键是唯一键,“01”是计数的 id,一个月的项目将在任何 id 获得该月的计数结果后立即创建。

{
  "details": {
    "01": {
      "a": {
        "count": [10, 5]
      },
      "b": {
        "count": [10, 5]
      }
    }
  },
  "time": "2020_06"
}
Run Code Online (Sandbox Code Playgroud)

我使用更新函数来保存计数结果:

var params = {
  TableName: tableName,
  Key: { time },
  UpdateExpression: `ADD details.#id.#type.count[0] :count0, details.#id.#type.count[1] :count1`,
  ExpressionAttributeNames: {
    '#id': id,
    '#type': type
  },
  ExpressionAttributeValues: {
    ':count0': count[0],
    ':count1': count[1]
  },
  ReturnValues: 'ALL_NEW'
}
Run Code Online (Sandbox Code Playgroud)

如果 id 的结果已经存在那就没问题了。但如果没有,我会收到一个错误消息

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

如何让地图先构建好再更新数据?我曾尝试使用SET if_not_exists(),但它会重叠我真正想要更新的路径(计数数组)

lee*_*gan 1

简而言之,你不能,我可以考虑两种选择。

  1. 创建项目时,创建一个空地图details。这将允许您更新嵌套值,而details不会引发有关无效路径的异常。

  2. 添加一些异常处理,如果第一次执行时抛出异常,它将更新整个映射:

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

Run Code Online (Sandbox Code Playgroud)