我正在使用DynamoDB作为K-V db(因为没有太多数据,我认为没问题),而'V'的一部分是列表类型(大约10个元素)。有一些会话要为它添加一个新值,我找不到在1个请求中执行此操作的方法。我做的是这样的:
item = self.list_table.get_item(**{'k': 'some_key'})
item['v'].append('some_value')
item.partial_save()
我首先请求服务器并在修改值后保存它。这不是原子的,看起来很难看。有没有办法在一个请求中执行此操作?
答案 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)
应该可以使用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