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

时间:2015-07-08 09:03:19

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

我正在使用DynamoDB作为K-V db(因为没有太多数据,我认为没问题),而'V'的一部分是列表类型(大约10个元素)。有一些会话要为它添加一个新值,我找不到在1个请求中执行此操作的方法。我做的是这样的:

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

我首先请求服务器并在修改值后保存它。这不是原子的,看起来很难看。有没有办法在一个请求中执行此操作?

4 个答案:

答案 0 :(得分:35)

以下代码适用于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'])

答案 1 :(得分:6)

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

  

SET支持以下功能:

     

...

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

您可以在Modifying Items and Attributes with Update Expressions documentation上看到一些相关示例:

  
      
  • 以下示例将新元素添加到 FiveStar 审核列表中。   表达式属性名称#pr ProductReviews ;属性   值: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上看到有关这些信息的更多信息。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

@LaserJesus的答案是正确的。但是,直接使用boto3有点痛苦,难以维护,而且根本不可重用。 dynamof提取掉那些垃圾。使用dynamof将项目附加到list属性看起来像:

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