简体   繁体   English

如何将值附加到 AWS DynamoDB 上的列表属性?

[英]How to append a value to list attribute on AWS DynamoDB?

I'm using DynamoDB as an KV db (cause there's not much data, I think that's fine) , and part of 'V' is list type (about 10 elements).我使用 DynamoDB 作为 KV 数据库(因为没有太多数据,我认为这很好),并且“V”的一部分是列表类型(大约 10 个元素)。 There's some session to append a new value to it, and I cannot find a way to do this in 1 request.有一些会话可以向其附加新值,但我找不到在 1 个请求中执行此操作的方法。 What I did is like this:我所做的是这样的:

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

I request the server first and save it after modified the value.我先请求服务器,修改值后保存。 That's not atomic and looks ugly.这不是原子的,看起来很难看。 Is there any way to do this in one request?有没有办法在一个请求中做到这一点?

The following code should work with boto3:以下代码适用于 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']

The get_dynamodb_resource method here is just:这里的 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'])

You can do this in 1 request by using the UpdateItem API in conjunction with an UpdateExpression .通过将UpdateItem API 与UpdateExpression结合使用,您可以在 1 个请求中完成此UpdateExpression Since you want to append to a list, you would use the SET action with the list_append function:由于您想附加到列表,您可以将SET操作与list_append函数一起使用:

SET supports the following functions: SET支持以下功能:

... ...

  • list_append (operand, operand) - evaluates to a list with a new element added to it. list_append (operand, operand) - 计算结果为添加了新元素的列表。 You can append the new element to the start or the end of the list by reversing the order of the operands.您可以通过反转操作数的顺序将新元素附加到列表的开头或结尾。

You can see a couple examples of this on the Modifying Items and Attributes with Update Expressions documentation :您可以在使用更新表达式修改项目和属性文档中看到这方面的几个示例:

  • The following example adds a new element to the FiveStar review list.以下示例向FiveStar评论列表添加了一个新元素。 The expression attribute name #pr is ProductReviews ;表达式属性名称#prProductReviews the attribute value :r is a one-element list.属性值:r是一个单元素列表。 If the list previously had two elements, [0] and [1] , then the new element will be [2] .如果列表之前有两个元素[0][1] ,那么新元素将是[2]

     SET #pr.FiveStar = list_append(#pr.FiveStar, :r)
  • The following example adds another element to the FiveStar review list, but this time the element will be appended to the start of the list at [0] .下面的示例将另一个元素添加到FiveStar评论列表,但这次该元素将附加到列表的开头[0] All of the other elements in the list will be shifted by one.列表中的所有其他元素都将移动一个。

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

The #pr and :r are using placeholders for the attribute names and values. #pr:r使用占位符作为属性名称和值。 You can see more information on those on the Using Placeholders for Attribute Names and Values documentation .您可以在“ 为属性名称和值使用占位符”文档中查看有关这些内容的更多信息。

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

Should be doable with an ADD, although not sure what the support in boto is for this.应该可以使用 ADD,尽管不确定 boto 中的支持是什么。

@LaserJesus 's answer is correct. @LaserJesus 的答案是正确的。 However, using boto3 directly is kind of a pain, hard to maintain, and not at all reusable.但是,直接使用 boto3 是一种痛苦,难以维护,并且根本无法重用。 dynamof abstracts that junk away. dynamof抽象了那些垃圾。 Using dynamof appending an item to a list attribute would look like:使用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')
  }))

disclaimer: I wrote dynamof免责声明:我写了dynamof

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM