DynamoDB conditional put - amazon-web-services

Say I want to add a record like below:
{
id:876876,
username:example,
email:xxxxxx#xxx.com,
phone:xxxxxxx,
created_at:current_date,
updated_at:current_date
}
What I want is to check with the id if record exist created_date should not be modified only updated_date should have current_date.
Can we do this with put method without having to be making a get item call?

To create a new item or update an existing item with conditional expression. Prefer to use updateItem rather than putItem.
If the Hash key (Primary key) doesn't exist both putItem and updateItem create a new record. If the record already exist, putItem will completely override the existing row but updateItem only updates the attributes passed in UpdateExpression not a whole record.
In your case, use if_not_exists() function to check whether the created_at field already exists or not. If exists created_at will not be overridden.
Update expression: "SET #email = :email, #created_at = if_not_exists(#created_at, :created_at), #updated_at = :updated_at"
Sample snippet
var params = {
ExpressionAttributeNames: {
"#email": "email",
"#created_at": "created_at",
"#updated_at": "updated_at"
},
ExpressionAttributeValues: {
":email": {
S: "test2#grr.la"
},
":created_at": {
S: date.toISOString()
},
":updated_at": {
S: date.toISOString()
}
},
Key: {
"id": {
S: "T1"
}
},
ReturnValues: "ALL_NEW",
TableName: "stack",
UpdateExpression: "SET #email = :email, #created_at = if_not_exists(#created_at, :created_at), #updated_at = :updated_at"
};
ddb.updateItem(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data);
})

Related

How to append an item to an array in DynamoDB

Hi im trying to append an item to a dynamoDB array.
exports.handler = (event,context,callback)=>{
let params = {
Key:{
"userName":event.userName,
},
UpdateExpression:"set #FutureTrips = list_append(if_not_exists(#FutureTrips,empty_list),country)",
ExpressionAttributeNames:{
"#FutureTrips" : "FutureTrips"
},
ExpressionAttributeValues: {
':country':["Japan"],
":empty_list":[]
},
TableName:"Users"
};
dynamoDB.updateItem(params,function(err,data){
if(err){
console.log(err);
callback(null,err);
}
else{
callback(null,data);
}
});
};
it returns me "message": "Unexpected key '0' found in params.ExpressionAttributeValues[':country']",
im trying to append an item to an array called FutureTrips
thanks for the help
Based on the code you share, currently the UpdateExpression is not referring to the specified ExpressionAttributeValues.
UpdateExpression:"set #FutureTrips = list_append(if_not_exists(#FutureTrips,empty_list),country)"
Correct UpdateExpression should be;
UpdateExpression: "set #FutureTrips = list_append(if_not_exists(#FutureTrips, :empty_list), :country)"

Removing the "reserved keyword" from dynamodb update item node js

I am able to SET values for reserved keywords but not able to remove certain keywords in dynamodb.
My expression is below. Not able to remove data if I give like this. But able to remove size though.
Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword:data
{
ConditionExpression: "#id = :id",
ExpressionAttributeNames: {
"#id": "id",
“#name": “name",
},
ExpressionAttributeValues: {
":id": “1234566",
“:name": “John",
},
Key: {
id: "1234566",
},
ReturnValues: "ALL_NEW",
TableName: “table_name",
UpdateExpression: "SET #name = :name REMOVE size, data",
}
Modified to include data in expression attribute names as below. Still throws error.
{
ConditionExpression: "#id = :id",
ExpressionAttributeNames: {
"#id": "id",
“#name": “name",
“#size": “size",
“#data": “data",
},
ExpressionAttributeValues: {
":id": “1234566",
“:name": “John",
“:size": undefined,
“:data": undefined,
},
Key: {
id: "1234566",
},
ReturnValues: "ALL_NEW",
TableName: "table_name",
UpdateExpression: "SET #name = :name, #size = :size, #data =
:data REMOVE size, data”,
}
Remove size and data from ExpressionAttributeValues and from SET UpdateExpression. Add #size and #data to REMOVE on UpdateExpression instead of size and data.
{
ConditionExpression: "#id = :id",
ExpressionAttributeNames: {
"#id": "id",
“#name": “name",
“#size": “size",
“#data": “data",
},
ExpressionAttributeValues: {
":id": “1234566",
“:name": “John"
},
Key: {
id: "1234566",
},
ReturnValues: "ALL_NEW",
TableName: "table_name",
UpdateExpression: "SET #name = :name, REMOVE #size, #data”,
}
Reserved words in DynamoDB
to do that dynamically you need only to provide a json object with this function
it's create dynamically
-ExpressionAttributeNames
-ExpressionAttributeValues
-UpdateExpression
also skip reserved keyword for dynamodb
def generate_update_att(body):
"""
#############input
body={
'newval':newData['newval'],
'lastname':newData['lastname'],
'name':newData['name']
}
#################output
-ExpressionAttributeNames
-ExpressionAttributeValues
-UpdateExpression
"""
UpdateExpression = ["set "]
ExpressionAttributeValues = dict()
ExpressionAttributeNames=dict()
for key, val in body.items():
UpdateExpression.append(f" #{key} = :{key},")
ExpressionAttributeValues[f":{key}"] = val
ExpressionAttributeNames[f"#{key}"] = key
return "".join(UpdateExpression)[:-1], ExpressionAttributeValues,ExpressionAttributeNames
function Call
my_data={
'newval':newData['newval'],
'lastname':newData['lastname'],
'name':newData['name']
}
a, v,z = generate_update_att(my_data)
my_table.update_item(
Key={'id':my_id},
UpdateExpression=my_UpdateExpression,
ExpressionAttributeValues=dict(my_ExpressionAttributeValues),
ExpressionAttributeNames=dict(my_ExpressionAttributeNames)
)

Amazon Lex and DynamodDB - can't update existing item

I'm trying to get a specific item from a table.
My DynamoDB table name is table and I have:
Name PK | Number<br/>
S: Juan | S: #####
When I try to run in Lambda I don't get any Item when it really exist one with that name... any idea why it's like that?
AWS = require("aws-sdk"),
DDB = new AWS.DynamoDB({
region: "REGION",
}),
lookup_name_str = name //From Intent variable,
params = {
TableName: "table",
KeyConditionExpression: "name = :v1",
ExpressionAttributeValues: {
":v1":{
"S": lookup_name_str
}
},
FilterExpression: 'contains(nomColaborador,:v1)',
ProjectionExpression: "Number"
};
console.log(params);
var docClient = new AWS.DynamoDB.DocumentClient();
docClient.scan(params, function(err, data){
if(err){
throw err;
}
if(data.Items && data.Items[0] && data.Items[0].Number){
console.log("There is a Name with that number");
console.log(data.Items[0]);
my_response.statusCode = 200;
my_response.body = {
"sessionAttributes": {
"extension_str": data.Items[0].Number.S,
"nomColaborador": event.currentIntent.slots.Name
},
"dialogAction":{
"type": "Close",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "PlainText",
"content": data.Items[0].Number.S
}
}
};
The main problem here is that you are doing a scan. KeyConditionExpression isn't a parameter of a scan request. If you are requesting a single item by key you want to use getItem. If you need to query data by partition key and an optional sort key you should use query.
With that all said, when you do a scan, or put a filter on a query, you really need to be sure to page through the data. You will often find that you'll get a response with no data, but a paging key to make another call.

DynamoDB Update - ExpressionAttributeNames can only be specified when using expressions

I need another set of eyes on this. For the life of me I see no issues with this parameter set, used for Dynamo DocumentClient, update method - (here: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#update-property ).
{
TableName: "mygame-dev",
Key: { pk: "09d017aa-cbf7-42ce-be6a-a94ecb58f9a7", sk: "GAME" },
ExpressionAttributeNames: { "#GAMELASTUPDATED": "gameLastUpdated", "#GAMETITLE": "gameTitle" },
ExpressionAttributeValues: { ":gamelastupdated": 1556376010704, ":gametitle": "test title 1" },
UpdateExpression: "SET #GAMELASTUPDATED = :gamelastupdated, #GAMETITLE = :gametitle",
ReturnValues: "ALL_NEW"
};
Error:
ValidationException: ExpressionAttributeNames can only be specified
when using expressions
Any thoughts?
Disregard, this was a copy and paste issue... I was using "query" not "update"
Was:
const updateGameResult = await ddbCall("query", params);
Should have been:
const updateGameResult = await ddbCall("update", params);

dynamodb in the browser getting started

I am little confused about retrieving data from dynamodb ... connecting is not an issue cause I am getting The provided key element does not match the schema
:the example provided from AWS
var table = new AWS.DynamoDB({params: {TableName: 'MY_TABLE'}});
var key = 'UNIQUE_KEY_ID';
var itemParams = {Item: {id: {S: key}, data: {S: 'data'}}};
table.getItem({Key: {id: {S: key}}}, function(err, data) {
console.log(data.Item); // print the item data
});
in my case the unique key is "time" and what I want to do is retrieve by key (not unique)
getItem only works on the primary key. From the docs: The GetItem operation returns a set of attributes for the item with the given primary key. See docs.
To solve this, create a Global Secondary Index that has "key" as HASH and "time" as RANGE. Then do a query operation using that index as IndexName:
var params = {
IndexName: 'your-new-GSI-index',
KeyConditionExpression: '#key = :key',
ExpressionAttributeNames: { '#key': 'key },
ExpressionAttributeValues: { ':key': { S: yourKeyVar } }
}
table.query(params, callback);
(did not test this code, but should work)