Adding new attribute to DynamDB table with updateItem - amazon-web-services

I have table already and I want to add a new attribute to that table.
I am trying to do that with the update_item functionality of dynamDB.
use case: Bid table holds details on the bid of the product. The user accepts the bid, once the bid is accepted, have to add a few attributes to that record like the user information. Not sure if it is the right way or should I have a new table for this.
pratition key is : Pickup,
sort key is : DropOff
A Demo example that I am trying currently
currently trying to alter the same table and facing the error.
import json
import boto3
def lambda_handler(event, context):
dynamo_client = boto3.resource('dynamodb')
users = dynamo_client.Table('LoadsandBids')
item = event['body']
print("Fuirst")
users.update_item(
Key={
'Pickup': event['body']['Pickup'],
'DropOff' : event['body']['DropOff']
},
UpdateExpression='SET #attr1 = :val1',
ExpressionAttributeNames={'#attr1': 'new_field'},
ExpressionAttributeValues={':val1': event['body']['new']},
ReturnValues='UPDATED_NEW'
)
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
getting an error:
"An error occurred (ValidationException) when calling the UpdateItem operation: The provided key element does not match the schema",
Could anyone help me out of this and also suggest it I my approach is good or not?

Related

Key element does not match the schema boto3 UpdateItem

I created a table on DynamoDB with partition key Robot (Number) ans sort key Status (string). I have written this code to update the Status of two items in a given condition through this code
import boto3
from boto3.dynamodb.conditions import Key
TABLE_NAME = "RobotStatus"
# Creating the DynamoDB Client
dynamodb_client = boto3.client('dynamodb', region_name="eu-central-1")
# Creating the DynamoDB Table Resource
dynamodb=boto3.resource('dynamodb', region_name="eu-central-1")
table=dynamodb.Table(TABLE_NAME)
# Use the DynamoDB client query method to get robot1's status
response=dynamodb_client.query(
TableName=TABLE_NAME,
KeyConditionExpression='Robot = :Robot',
ExpressionAttributeValues={
':Robot': {'N': "1"}
}
)
if response['Items'][0]['Status']['S'] == "disconnected":
response=table.update_item(
Key={'Robot': "2"},
UpdateExpression = "set #st = :s",
ExpressionAttributeValues={":s" : "disconnecting"},
ExpressionAttributeNames={"#st":"Status"},
ReturnValues="UPDATED_NEW"
)
response=table.update_item(
Key={'Robot': "3"},
UpdateExpression="set #st = :s",
ExpressionAttributeValues = {":s" : "disconnecting"},
ExpressionAttributeNames={"#st":"Status"},
ReturnValues="UPDATED_NEW"
)
but once I run the script this error pops up
botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the UpdateItem operation: The provided key element does not match the schema
I have also tried to add the sort key inside the Key field of UpdateItem but nothing changes, do you know what could be the problem?

Dynamically Insert/Update Item in DynamoDB With Python Lambda using event['body']

I am working on a lambda function that gets called from API Gateway and updates information in dynamoDB. I have half of this working really dynamically, and im a little stuck on updating. Here is what im working with:
dynamoDB table with a partition key of guild_id
My dummy json code im using:
{
"guild_id": "126",
"guild_name": "Posted Guild",
"guild_premium": "true",
"guild_prefix": "z!"
}
Finally the lambda code:
import json
import boto3
def lambda_handler(event, context):
client = boto3.resource("dynamodb")
table = client.Table("guildtable")
itemData = json.loads(event['body'])
guild = table.get_item(Key={'guild_id':itemData['guild_id']})
#If Guild Exists, update
if 'Item' in guild:
table.update_item(Key=itemData)
responseObject = {}
responseObject['statusCode'] = 200
responseObject['headers'] = {}
responseObject['headers']['Content-Type'] = 'application/json'
responseObject['body'] = json.dumps('Updated Guild!')
return responseObject
#New Guild, Insert Guild
table.put_item(Item=itemData)
responseObject = {}
responseObject['statusCode'] = 200
responseObject['headers'] = {}
responseObject['headers']['Content-Type'] = 'application/json'
responseObject['body'] = json.dumps('Inserted Guild!')
return responseObject
The insert part is working wonderfully, How would I accomplish a similar approach with update item? Im wanting this to be as dynamic as possible so I can throw any json code (within reason) at it and it stores it in the database. I am wanting my update method to take into account adding fields down the road and handling those
I get the follow error:
Lambda execution failed with status 200 due to customer function error: An error occurred (ValidationException) when calling the UpdateItem operation: The provided key element does not match the schema.
A "The provided key element does not match the schema" error means something is wrong with Key (= primary key). Your schema's primary key is guild_id: string. Non-key attributes belong in the AttributeUpdate parameter. See the docs.
Your itemdata appears to include non-key attributes. Also ensure guild_id is a string "123" and not a number type 123.
goodKey={"guild_id": "123"}
table.update_item(Key=goodKey, UpdateExpression="SET ...")
The docs have a full update_item example.

DynamoDB Conditional Put_Item

Hi Stackoverflow I'm trying to conditionally put an item within a DynamoDB table. The DynamoDB table has the following attributes.
ticker - Partition Key
price_date - Sort Key
price - Attribute
Every minute I'm calling an API which gives me a minute by minute list of dictionaries for all stock prices within the day so far. However, the data I receive from the API sometimes can be behind by a minute or two. I don't particularly want to overwrite all the records within the DynamoDB table every time I get new data. To achieve this I've tried to create a conditional expression to only use put_item when there is a match on ticker but there is a new price_date
I've created a simplification of my code below to better illustrate my problem.
import boto3
from boto3.dynamodb.conditions import Attr
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('stock-intraday')
data = [
{'ticker': 'GOOG', 'price_date': '2021-10-08T9:30:00.000Z', 'price': 100},
{'ticker': 'GOOG', 'price_date': '2021-10-08T9:31:00.000Z', 'price': 101}
]
for item in data:
dynamodb_response = table.put_item(Item=item,
ConditionExpression=Attr("ticker").exists() & Attr("price_date").not_exists())
However when I run this code I get this error...
What is wrong with my conditional expression?
Found an answer to my own problem. DynamoDB was throwing an error because my code WAS working but with some minor changes.
There needed to be a TRY EXCEPT block but also since the partition key is already evaluated only the price_date needed to be included within the condition expression
import boto3
from boto3.dynamodb.conditions import Attr
from botocore.exceptions import ClientError
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('stock-intraday')
data = [
{'ticker': 'GOOG', 'price_date': '2021-10-08T9:30:00.000Z', 'price': 100},
{'ticker': 'GOOG', 'price_date': '2021-10-08T9:31:00.000Z', 'price': 101}]
for item in data:
try:
dynamodb_response = table.put_item(Item=item,
ConditionExpression=Attr("price_date").not_exists())
except ClientError as e:
if e.response['Error']['Code'] == 'ConditionalCheckFailedException':
pass

Unable to PUT to DynamoDB from a Python Lambda function

Im using a Lambda function to get and put data to DynamoDB.
I am able to put a new item into my table, but when I try to pass anything other than KEY I get the following error:
An error occurred (ValidationException) when calling the UpdateItem operation:
The provided key element does not match the schema
This works (with key only):
"body": "{\"TableName\":\"myExampleTableName\",\"Key\":{\"id\": {\"S\": \"SomeID\"}}}"
This throws error(with key and some data):
"body": "{\"TableName\":\"myExampleTableName\",\"Key\":{\"id\": {\"S\": \"SomeID\"},\"Data\": {\"S\": \"MyDataExampleData\"}}}"
Although it seems to be the same syntax as the example shows here.
Anybody see what I am doing wrong?
Here's the my body in a more readable way:
{
"TableName":"myExampleTableName",
"Key":{
"id": {"S": "SomeID"},
"Data": {"S": "MyDataExampleData"}
}
}
The "Data" field inside the "Key" doesn't seem right. It would be easier to understand if we had the actual code and the schema of the table you're trying to put.
This is an example using python, where you can see that there's no "Key" attribute, but "Item" (I'm assuming you're using python based on the doc you've sent)
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Python.03.html
response = table.put_item(
Item={
'year': year,
'title': title,
'info': {
'plot': plot,
'rating': rating
}
}
)

Get Item from a table in Dynamodb AWS

I am trying to get_item from a table in dynamodb.
def read_table_item(table_name, pk_name, pk_value):
"""
Return item read by primary key.
"""
table = dynamodb.Table(table_name)
response = table.get_item( Key={pk_name: pk_value})
return response
print (read_table_item(table_name,pk_name="_id",pk_value={"S":str(1)}))
The error I get is
"botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the GetItem operation: The provided key element does not match the schema"
It will be helpful if somebody review the above piece and help us rectify the issue.
Thanks
it seems to me what ever you are passing to pk_name is not in the DynamodbSchema. See following for more informaton.
Incorrect dynamo db key mapping