简体   繁体   English

更新在 dynamodb 中添加属性的项目

[英]update an item adding an attribute in dynamodb

Is it not possible to add an attribute in dynamodb dynamically?是否无法在 dynamodb 中动态添加属性?

I got this error when I tried-" The provided key element does not match the schema ".当我尝试-“提供的关键元素与架构不匹配”时出现此错误。

Scenario -场景——

{ id : "123",
  imageName : "elephant.jpg"
}

I want to add an attribute - imagePath : "/path/to/image" to the above data.我想在上面的数据中添加一个属性 - imagePath : "/path/to/image"。 I used put_item, but it replaces the old item if exists.我使用了 put_item,但它会替换旧项目(如果存在)。

I am searching for the solution for - If id = "123", then add imagePath attribute else add a new item to the table.我正在寻找解决方案 - If id = "123", then add imagePath attribute else add a new item to the table.

Adding an attribute can be achieved using put_item but it will replace the existing item.可以使用 put_item 添加属性,但它将替换现有项目。 How can we dynamically add an attribute to the existing data using update_item ?我们如何使用 update_item 向现有数据动态添加属性? (appending imagePath to the the given json) (将 imagePath 附加到给定的 json)

Should I alter the schema of the table with imagePath and then use update_item function?我应该使用 imagePath 更改表的架构,然后使用 update_item 函数吗?

How can we achieve this using python?我们如何使用 python 实现这一目标?

Unfortunately, it can't be achieved in single step.不幸的是,它不能一步完成。 However, it can be achieved in two step process:-但是,它可以通过两步过程来实现:-

1) Try to insert the data conditionally ie if the key value is already present don't perform any operation (ie insert or update - nothing happens) 1) 尝试有条件地插入数据,即如果键值已经存在,则不执行任何操作(即插入或更新 - 没有任何反应)

2) If there is a ConditionalCheckFailedException , then update the item 2) 如果有ConditionalCheckFailedException ,则更新该项

Sample code:-示例代码:-

In the below code, usertable is the table name.在下面的代码中, usertable是表名。 The key attributes of the table are userid and score .该表的关键属性是useridscore You need to change the below code accordingly for your table structure.您需要为您的表结构相应地更改以下代码。

Also, I have assigned the key value (as "Mike").另外,我已经分配了键值(如“Mike”)。 You need to change it accordingly for your use case.您需要根据您的用例相应地更改它。

from __future__ import print_function # Python 2/3 compatibility
from boto.dynamodb2.exceptions import ConditionalCheckFailedException
from botocore.exceptions import ClientError
from boto3.dynamodb.conditions import Attr
import boto3
import json
import decimal

# Helper class to convert a DynamoDB item to JSON.
class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            if o % 1 > 0:
                return float(o)
            else:
                return int(o)
        return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://localhost:8000")

table = dynamodb.Table('usertable')

userId = "Mike"

try :
    response = table.put_item(
    Item={
            'userid': userId,
            'score' : 100,
            'imagePath' : '/path/to/image'        
        },
        ConditionExpression=Attr('userid').ne(userId)        
    )

    print("Conditional PutItem succeeded:")
    print(json.dumps(response, indent=4, cls=DecimalEncoder))
except ClientError as ce :    
    print("Conditional check failed:", ce)
    if ce.response['Error']['Code'] == 'ConditionalCheckFailedException':
        print("Key already exists")
        response = table.update_item(
            Key={'userid': userId, 'score' : 100},
            UpdateExpression="set imagePath = :imagePathVal",
            ExpressionAttributeValues={":imagePathVal" : "/path/to/image" }
        )
        print("Update existing item succeeded:")
        print(json.dumps(response, indent=4, cls=DecimalEncoder))        
    else:
        print("Unexpected error: %s" % e

) )

Update:-更新:-

The data type of variable id and key attribute RequestId should match.变量id的数据类型和关键属性RequestId应该匹配。

Lastest version of update_item will handle attribute creation if does not already exists如果不存在,update_item 的最新版本将处理属性创建

import boto3 
from boto3.dynamodb.conditions import Key

def query_status(asset_id, dynamodb, table):
    try:        
        response = table.query(
            ProjectionExpression="#asset_id, status_id" ,
            ExpressionAttributeNames={"#asset_id": "asset_id"},
            KeyConditionExpression=Key('asset_id').eq(asset_id)        
        )
        if response['Items']:
            return response['Items'][0]["status_id"]
    except:
        pass # if attribute does not exists, return None

    
 
def update_asset_status(asset_id, status_id, dynamodb, table):  
    response = table.update_item(
        Key={'asset_id': asset_id},
        UpdateExpression="set status_id=:r",
        ExpressionAttributeValues={':r': status_id},
        ReturnValues="UPDATED_NEW"
    )
    return response



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

asset_id='1234'

print("Current Status: ", query_status(asset_id, dynamodb, table))

new_status_id='4'
update_asset_status(asset_id, new_status_id, dynamodb, table)

print("New Status: ", query_status(id, dynamodb, table))

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

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