【问题标题】:How to append a value to list attribute on AWS DynamoDB?如何将值附加到 AWS DynamoDB 上的列表属性?
【发布时间】:2020-02-01 13:24:20
【问题描述】:

我将 DynamoDB 用作 K-V db(因为没有太多数据,我认为这很好),并且“V”的一部分是列表类型(大约 10 个元素)。有一些会话可以为其附加一个新值,但我无法在 1 个请求中找到执行此操作的方法。我的做法是这样的:

item = self.list_table.get_item(**{'k': 'some_key'})
item['v'].append('some_value')
item.partial_save()

我先请求服务器,修改值后保存。这不是原子的,看起来很丑。有没有办法在一个请求中做到这一点?

【问题讨论】:

    标签: python amazon-web-services amazon-dynamodb boto


    【解决方案1】:

    以下代码应与 boto3 一起使用:

    table = get_dynamodb_resource().Table("table_name")
    result = table.update_item(
        Key={
            'hash_key': hash_key,
            'range_key': range_key
        },
        UpdateExpression="SET some_attr = list_append(some_attr, :i)",
        ExpressionAttributeValues={
            ':i': [some_value],
        },
        ReturnValues="UPDATED_NEW"
    )
    if result['ResponseMetadata']['HTTPStatusCode'] == 200 and 'Attributes' in result:
        return result['Attributes']['some_attr']
    

    这里的get_dynamodb_resource方法就是:

    def get_dynamodb_resource():
        return boto3.resource(
                'dynamodb',
                region_name=os.environ['AWS_DYNAMO_REGION'],
                endpoint_url=os.environ['AWS_DYNAMO_ENDPOINT'],
                aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'],
                aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'])
    

    【讨论】:

    • 谢谢!这完美地工作。虽然我尝试使用 ADD 但这没有用。我在他们推荐使用 ADD 的文档中读到。当我尝试使用 ADD 时,UpdateExression 中出现运算符不匹配错误。
    • 非常有用!对不起,我只能 +1 :(
    • 列表项必须存在吗?或者我可以使用它,如果它不存在,它会为我初始化 some_attr 作为一个空列表?
    • 如果列表不存在需要创建列表,请查看stackoverflow.com/questions/34951043/…
    • 完全支持 vnpnlz(也很抱歉我只能 +1)。
    【解决方案2】:

    您可以将UpdateItem API 与UpdateExpression 结合使用,在1 个请求中执行此操作。由于您想追加到列表,您可以使用 SET 操作和 list_append 函数:

    SET支持以下功能:

    ...

    • list_append (operand, operand) - 评估为一个新的列表 元素添加到它。您可以将新元素附加到开头或 通过反转操作数的顺序来结束列表。

    您可以在Modifying Items and Attributes with Update Expressions documentation 上看到几个这样的例子:

    • 以下示例将一个新元素添加到 FiveStar 评论列表。 表达式属性名称#prProductReviews;属性 值:r 是一个元素列表。如果列表以前有两个 元素,[0][1],那么新元素将是 [2]

      SET #pr.FiveStar = list_append(#pr.FiveStar, :r)
      
    • 以下示例将另一个元素添加到 FiveStar 评论 列表,但这次元素将附加到列表的开头 在[0] 列出。列表中的所有其他元素将移动 一个。

      SET #pr.FiveStar = list_append(:r, #pr.FiveStar)
      

    #pr:r 使用占位符来表示属性名称和值。您可以在Using Placeholders for Attribute Names and Values documentation 上查看更多信息。

    【讨论】:

      【解决方案3】:

      我会看看更新表达式: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Modifying.html#Expressions.Modifying.UpdateExpressions.ADD

      应该可以使用 ADD,但不确定 boto 对此的支持是什么。

      【讨论】:

        【解决方案4】:

        @LaserJesus 的回答是正确的。但是,直接使用 boto3 有点痛苦,难以维护,而且根本无法重用。 dynamof 抽象出那些垃圾。使用dynamof 将项目附加到列表属性如下所示:

        from functools import partial
        from boto3 import client
        from dynamof.executor import execute
        from dynamof.operations import update
        from dynamof.attribute import attr
        
        client = client('dynamodb', endpoint_url='http://localstack:4569')
        db = partial(execute, client)
        
        db(update(
          table_name='users',
          key={ 'id': user_id },
          attributes={
              'roles': attr.append('admin')
          }))
        

        免责声明:我写了 dynamof

        【讨论】:

          猜你喜欢
          • 2018-10-09
          • 1970-01-01
          • 1970-01-01
          • 2019-02-11
          • 2018-10-10
          • 1970-01-01
          • 2019-11-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多