2017-10-10 93 views
1

是否無法動態添加dynamodb屬性?更新添加dynamodb屬性的項目

當我嘗試 - 「提供的關鍵元素與模式不匹配時,我得到了此錯誤」。

方案 -

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

我要添加的屬性 - 的ImagePath: 「/路徑/到/圖像」,以上面的數據。 我使用了put_item,但它會替換舊的項目(如果存在)。

我正在尋找解決方案 - 如果id =「123」,然後添加imagePath屬性,否則添加一個新的項目到表中。

使用put_item可以實現添加屬性,但它會替換現有的項目。 我們如何使用update_item動態添加屬性到現有數據?(將imagePath添加到給定的json)

我應該用imagePath更改表的模式,然後使用update_item函數嗎?

我們如何使用python來實現這一點?

+0

你使用的是什麼代碼? – Kannaiyan

+0

@Kannaiyan我編輯了這個問題。 – manojpt

回答

2

不幸的是,它不能一步到位。但是,它可以在兩個步驟來實現: -

1)儘量插入數據有條件即如果鍵值已經存在不執行任何操作(即插入或更新 - 什麼也沒有發生)

2)如果有ConditionalCheckFailedException,然後更新項目

示例代碼: -

在下面的代碼,usertable是表名。該表的關鍵屬性是useridscore。您需要相應地更改表格結構的以下代碼。

另外,我已經分配了鍵值(如「Mike」)。您需要根據自己的用例對其進行相應更改。

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 

更新: -

可變id和密鑰屬性RequestId的數據類型應該匹配。

+0

期望塊仍然會給出錯誤「提供的關鍵元素與模式不匹配」​​,因爲imagePath是我嘗試添加的動態字段(imagePath不在表模式中)。這是什麼解決方案? @notionquest – manojpt

+0

Dynamodb接受動態字段。您不需要定義架構中的所有字段。在更新項目API中,您需要正確使用鍵屬性。你的分區鍵和分類鍵是什麼? – notionquest

+0

您的分區鍵屬性名稱是RequestId還是Id? – notionquest