dynamodb boto3中update_item的示例

时间:2015-12-24 04:38:21

标签: python amazon-dynamodb boto3 botocore

关注the documentation,我试图创建一个更新或添加的更新语句,如果不存在,则只在dynamodb表中存在一个属性。

我正在尝试这个

response = table.update_item(
    Key={'ReleaseNumber': '1.0.179'},
    UpdateExpression='SET',
    ConditionExpression='Attr(\'ReleaseNumber\').eq(\'1.0.179\')',
    ExpressionAttributeNames={'attr1': 'val1'},
    ExpressionAttributeValues={'val1': 'false'}
)

我得到的错误是:

botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the UpdateItem operation: ExpressionAttributeNames contains invalid key: Syntax error; key: "attr1"

如果有人做了类似于我想要实现的任何事情,请分享示例。

5 个答案:

答案 0 :(得分:31)

找到工作示例here,列出表的所有索引非常重要,这在更新之前需要额外的查询,但是它可以工作。

{{1}}

答案 1 :(得分:9)

如果您不想按参数检查更新,我写了一个很酷的函数,该函数将返回所需的参数以使用boto3执行 update_item 方法。

<template>
  <div class="app">
  <div class="app-Inner">
  </div>
  <button @click="getLocation">VIEW YOUR LOCATION</button>
  <div>{{ width }}</div>
  <div class="location"></div>
  <div class="map"></div>
  </div>
</template>

<script>
import Home from './components/Home.vue';
import MainValues from './components/MainValues.vue';
import Form from './components/Form.vue';
import More from './components/More.vue';
export default {
  name: 'App',
  data() {
    return {
      width: 0,
      height: 0,
    };
  },
  methods: {
    getLocation() {
      const geo = navigator.geolocation;
      if (geo) {
        // eslint-disable-next-line
        geo.getCurrentPosition(showLocation);
      } else {
        const divLocation2 = document.querySelector('.location');
        divLocation2.innerHTML = 'error';
      }
      function showLocation(location) {
        // edit: !!!
        // here instead of sending location cords through innerHTML i 
        // want to assign them into variables "width" and "height" which
        // are defined in "data()" function above. 
        // tried: this.width = location.coords.latitude, and
        // also : this.length = location.coords.longitude
        // !!!
        const divLocation = document.querySelector('.location');
        divLocation.innerHTML = `${location.coords.latitude} ${location.coords.longitude}`;
      }
    },
  },
};
</script>

这是一个简单的例子:

def get_update_params(body):
    """Given a dictionary we generate an update expression and a dict of values
    to update a dynamodb table.

    Params:
        body (dict): Parameters to use for formatting.

    Returns:
        update expression, dict of values.
    """
    update_expression = ["set "]
    update_values = dict()

    for key, val in body.items():
        update_expression.append(f" {key} = :{key},")
        update_values[f":{key}"] = val

    return "".join(update_expression)[:-1], update_values

答案 2 :(得分:4)

有关使用boto3的dynamodb更新的详细信息在网上看起来非常稀疏,所以我希望这些替代解决方案很有用。

获取/放置

import boto3

table = boto3.resource('dynamodb').Table('my_table')

# get item
response = table.get_item(Key={'pkey': 'asdf12345'})
item = response['Item']

# update
item['status'] = 'complete'

# put (idempotent)
table.put_item(Item=item)

实际更新

import boto3

table = boto3.resource('dynamodb').Table('my_table')

table.update_item(
    Key={'pkey': 'asdf12345'},
    AttributeUpdates={
        'status': 'complete',
    },
)

答案 3 :(得分:4)

原始代码示例:

response = table.update_item(
    Key={'ReleaseNumber': '1.0.179'},
    UpdateExpression='SET',
    ConditionExpression='Attr(\'ReleaseNumber\').eq(\'1.0.179\')',
    ExpressionAttributeNames={'attr1': 'val1'},
    ExpressionAttributeValues={'val1': 'false'}
)

已修复:

response = table.update_item(
    Key={'ReleaseNumber': '1.0.179'},
    UpdateExpression='SET #attr1 = :val1',
    ConditionExpression=Attr('ReleaseNumber').eq('1.0.179'),
    ExpressionAttributeNames={'#attr1': 'val1'},
    ExpressionAttributeValues={':val1': 'false'}
)

在标记的答案中,还显示有一个范围键,因此也应包含在Key中。 update_item方法必须查找要更新的确切记录,没有批处理更新,并且您不能将经过过滤的值范围更新为获取单个记录的条件。 ConditionExpression可以使更新幂等;即如果已经是该值,则不要更新该值。它不像sql where子句。

关于看到的特定错误。

ExpressionAttributeNames是要在UpdateExpression中使用的键占位符列表,如果键是保留字,则很有用。

在文档中,“表达式属性名称必须以#开头,后跟一个或多个字母数字字符”。该错误是因为代码没有使用以#开头的ExpressionAttributeName,也没有在UpdateExpression中使用它。

ExpressionAttributeValues是要更新为的值的占位符,它们必须以:

开头

答案 4 :(得分:1)

基于official example,这是一个简单而完整的解决方案,可用于手动更新(我不建议这样做)terraform S3后端使用的表。

假设这是AWS CLI所示的表数据:

$ aws dynamodb scan --table-name terraform_lock --region us-east-1
{
    "Items": [
        {
            "Digest": {
                "S": "2f58b12ae16dfb5b037560a217ebd752"
            },
            "LockID": {
                "S": "tf-aws.tfstate-md5"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

您可以将其更新为新的摘要(例如您已回滚状态),如下所示:

import boto3

dynamodb = boto3.resource('dynamodb', 'us-east-1')


try:
    table = dynamodb.Table('terraform_lock')
    response = table.update_item(
        Key={
            "LockID": "tf-aws.tfstate-md5"
        },
        UpdateExpression="set Digest=:newDigest",
        ExpressionAttributeValues={
            ":newDigest": "50a488ee9bac09a50340c02b33beb24b"
        },
        ReturnValues="UPDATED_NEW"
    )
except Exception as msg:
    print(f"Oops, could not update: {msg}")

请注意,:":newDigest": "50a488ee9bac09a50340c02b33beb24b"的开头很容易错过或忘记。