DynamoDB Validation Exception - Key element does not match the schema - javascript

I'm trying to get an item from my DynamoDB but get the following error
ValidationException: The provided key element does not match the
schema
The create item piece of the code works. But no the Get item.
Table Info:
Table Name: movieTable
Primary Partition Key: itemID
Primary Sort Key: sortKey
Here's the code for the create and update:
var fbUserId;
var params;
var keyText;
var attText;
var valText;
var dynamodb = null;
var docClient = null;
var appId = '405140756489952'; //from facebook
var roleArn = 'arn:aws:iam::042765862882:role/Verzosa'; //from AWS IAM
var resultData = null;
document.getElementById('putThis').onclick = function () {
dynamodb = new AWS.DynamoDB({ region: 'us-west-2' });
docClient = new AWS.DynamoDB.DocumentClient({ service: dynamodb });
keyText = document.getElementById("keyValue").value;
attText = document.getElementById("attributeText").value;
valText = document.getElementById("valueText").value;
console.log("Key Value: ", keyText);
console.log("Attribute: ", attText);
console.log("Value: ", valText);
params = {
TableName: 'movieTable',
Item: {
itemID: keyText,
sortKey: valText
}
};
docClient.put(params, function(err, data){
if (err) console.log(err);
else
{
resultData = data;
console.log(resultData);
}
})
};
document.getElementById('getThis').onclick = function () {
dynamodb = new AWS.DynamoDB({ region: 'us-west-2' });
docClient = new AWS.DynamoDB.DocumentClient({ service: dynamodb });
keyText = document.getElementById("keyValue").value;
attText = document.getElementById("attributeText").value;
console.log("Key Value: ", keyText);
console.log("Attribute: ", attText);
params = {
TableName: 'movieTable',
Key: {
itemID: keyText,
},
ProjectionExpression: "#a",
ExpressionAttributeNames: {
'#a': attText
}
};
docClient.get(params, function (err, data)
{
if (err)
{
console.log(err, err.stack);
}
else
{
console.log("success, logging data: ");
console.log(data);//shows keys
console.log("attribute 1 is " + data.Item.sortKey)
//var output = data.Item.attribute1;
l = document.getElementById("output");
l.innerHTML = data.Item.sortKey;
}
})
};
Any help would be appreciated.

You are getting this error because when using AWS.DynamoDB.DocumentClient.get method, you must specify both hash and sort key of an item. But you have only hash key specified (itemId), and sort key is missing.
Here is how your get params should look like:
...
params = {
TableName: 'movieTable',
Key: {
itemID: keyText,
sortKey: valText // <--- sort key added
},
ProjectionExpression: "#a",
ExpressionAttributeNames: {
'#a': attText
}
};
docClient.get(params, function (err, data) {
...
If you'd like to get a record with a hash key only, without specifying its sort key, you should use query method instead of get:
...
params = {
TableName: 'movieTable',
KeyConditionExpression: '#itemID = :itemID',
ProjectionExpression: "#a",
ExpressionAttributeNames: {
'#a': attText,
'#itemID': 'itemID'
},
ExpressionAttributeValues: {
':itemID': keyText
}
};
dynamodbDoc.query(params, function(err, data) {
...
Be aware that while get method always returns 1 or no records, query can possibly return multiple records, so you would have to revisit your current implementation of get callback (e.g. instead of accessing data.Item you should use data.Items array, see query method docs)

You need to pass both primary key and sort key in the params.
You can find these keys from the table UI.
and you should pass those as parameters when making the request
this.ProjectsModel.delete({pk1:"project#giri-test#appsc", sk1:"metadata#giri-test#appsc"}, (error) => {
if (error) {
console.error(error);
} else {
console.log("Successfully deleted item");
}
});

Related

GetItem by date in DynamoDB results in ValidationException

I need a data filtered by date but I am getting an error
Error ValidationException: The provided key element does not match the schema
My table has a primary key (only partition key) of id.
async function fetchDatafromDatabase() { // get method fetch data from dynamodb
var date = todayDate();
var params = {
TableName: table,
Key: {
"date": date
}
};
let queryExecute = new Promise((res, rej) => {
dynamoDB.get(params, function (err, data) {
if (err) {
console.log("Error", err);
rej(err);
} else {
console.log("Success! get method fetch data from dynamodb");
res(JSON.stringify(data, null, 2));
}
});
});
const result = await queryExecute;
console.log(result);
}
For getting an item from DynamoDB, we must pass primary key, in this case, its just partition key 'id' (assuming it is numeric and storing epoc date)
var documentClient = new AWS.DynamoDB.DocumentClient();
var date = Date.now();
console.log("date", date);
var params = {
TableName: "test2",
Key: {
id: date,
},
};
documentClient.get(params, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
Complete Example to put an item and get it.
var documentClient = new AWS.DynamoDB.DocumentClient();
var date = Date.now();
documentClient.put(
{
TableName: "test2",
Key: {
id: date,
},
},
function (err, data) {
if (err) console.log("err", err);
if (data) {
documentClient.get(
{
TableName: "test2",
Key: {
id: date,
},
},
function (errGet, dataGet) {
if (errGet) {
console.log("Error", errGet);
} else {
console.log("Success", dataGet);
}
}
);
}
}
);

AWS Dynamodb not fetching data synchronously by node js

I am new on node js dynamo db I wrote a node js sdk to fetch one row from a table ona dynamodb. It is fetching data correctly but not immediately for this I got error
My code is below a simple code
var AWS = require("aws-sdk");
var config = function(){
AWS.config.update({region: 'us-east-1'});
// Create the DynamoDB service object
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
var params = {
TableName: 'tblConfigs',
// Key: {
// "id" : {S: "1"},
// }
ExpressionAttributeValues: {
":v1": {
S: "1"
}
},
FilterExpression: "id = :v1",
};
var v;
var json = ddb.scan(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
v = data;
// console.log(JSON.stringify(data.Item));
// return JSON.stringify(data.Item);
}
});
// if(v=="u")
// for(var i=0;)
v = v.Items[0];
// for()
var con = {
"host": v.endpoint.S,
"user": v.endpoint.username.S,
"password": v.endpoint.password.S,
"database": v.endpoint.database_name.S
};
return con;
}
And I got the below error
> config()
TypeError: Cannot read property 'Items' of undefined
at config (repl:31:7)
as v is undefined so it is giving the error but v is not undefined when I execute the code in node console it first time gave undefined next time it gave value
like below
> v
{ Items:
[ { password: [Object],
stage: [Object],
username: [Object],
id: [Object],
endpoint: [Object],
database_name: [Object] } ],
Count: 1,
ScannedCount: 1 }
how can I fetch the row immediately not after some time? IS there any good way in dynamodb I tried, get, getItem, scan, query all are giving data correctly but not immediately...Please suggest
You are missing one important thing: Javascript execution is asynchronous. As long as you are not using async/await syntax you have to "play" with callbacks like this:
var ddb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });
function loadConfig(callback) {
var params = {
TableName: 'tblConfigs',
ExpressionAttributeValues: {
':v1': {
S: '1'
}
},
FilterExpression: 'id = :v1'
};
ddb.scan(params, function (error, data) {
if (error) {
callback(error);
} else {
var item = data.Items[0];
callback(null, {
'host': item.endpoint.S,
'user': item.endpoint.username.S,
'password': item.endpoint.password.S,
'database': item.endpoint.database_name.S
});
}
});
}
loadConfig(function (error, configuration) {
if (error) {
console.log(error);
} else {
// Your connection logic (JUST AN EXAMPLE!)
var connection = mysql.connect({
host: configuration.host,
user: configuration.user,
password: configuration.password,
database: configuration.database
})
}
});
Btw. storing database configurations in DynamoDB isn't a good solution, i would recommend to check AWS Systems Manager Parameter Store.
Edit
To give you a short example how the async/await syntax looks like
var ddb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });
const loadConfig = async () => {
const { Items } = await ddb.scan({
TableName: 'tblConfigs',
ExpressionAttributeValues: {
':v1': {
S: '1'
}
},
FilterExpression: 'id = :v1'
}).promise();
const item = Items[0];
return {
'host': item.endpoint.S,
'user': item.endpoint.username.S,
'password': item.endpoint.password.S,
'database': item.endpoint.database_name.S
};
};

Having difficulty with DynamoDB query

I'm trying to wrap my head around AWS DynamoDB and having trouble getting records.
If my db item looks like this:
{
"id": string (primary)
"identifier": string
"project": string
}
I'm trying to get a record using both identifier and project:
Right now I'm doing that like this:
const params = {
TableName: 'MY_TABLE',
ExpressionAttributeValues: {
':identifier': { S : 'Dave' },
':project': { S : 'red_squad' },
},
KeyConditionExpression: 'identifier = :identifier and project = :project'
}
docClient
.query(
params,
(err, data) => console.log(err || data)
)
However it's telling me that it needs the primary key, however I that's not suitable for my use case.
Use a scan, not a query
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#scan-property
const params = {
TableName: 'MY_TABLE',
ExpressionAttributeValues: {
':identifier': { S : 'Dave' },
':project': { S : 'red_squad' },
},
FilterExpression: 'identifier = :identifier and project = :project'
}
docClient
.scan(
params,
(err, data) => console.log(err || data)
)

mongoose js won't print out query value

I want to create using mongoose js a collection of kitten with this document in it {name: "mike"}.
After creating this document I want to print it's value.
I wrote this code below.
2 problems:
this code doesn't end (meaning when I wrote node file.js the cmd line stays open (stucked) and no return value is return (infinite loop like in a server).
the code doesn't print the value of "mike". just create this doucument...
what am I doing wrong?
thanks
var mongoose = require('mongoose');
var url = 'mongodb://Yotam:Yotam#ds023475.mlab.com:23475/small-talkz';
mongoose.connect(url);
var kittySchema = mongoose.Schema({
name: String
});
var Kitten = mongoose.model('kitten', kittySchema);
Kitten.create({ name: "mike" }, function (err, small) {
if (err) return handleError(err);
});
Kitten.findOne( { } ), function(err, docs){
console.log(docs.name);
};
return 1;
newKitten = { name: "mike" };
Kitten.create(newKitten, function (err, kitty) {
if {
(err) return handleError(err);
} else {
console.log(kitty); //OR console.log(kitty.name);
}
});
Kitten.findOne({name: "mike"}).exec(function(e, kitten) {
if (e) {
console.log(e)
} else {
console.log(kitten.name)
}
});
the problem was {for anyone whose intersted (and thanks for herkou)} that I did not use the exec command..
This works:
Kitten.findOne( { name: "mike"} ).exec( function(err, docs){
console.log(docs.name);
return;
});
update:
also had a probelm with race conditions... the create of the documnet not finished when the query was called. that is why I got undeinfed.
use this new code:
var mongoose = require('mongoose');
var url = 'mongodb://Yotam:Yotam#ds023475.mlab.com:23475/small-talkz';
mongoose.connect(url);
var kittySchema = mongoose.Schema({
name: String,
color:String
});
var Kitten = mongoose.model('Kitten', kittySchema);
var newKitten = { name: "mike", color:"white" };
Kitten.create(newKitten, function (err, kitty) {
if (err) {
return handleError(err);
} else {
call_query();
}
});
var call_query= function(){
var query= Kitten.findOne( { name: "mike"} );
query.exec( function(err, docs){
console.log(docs.color);
return;
});
}
return 1;
now I just need to understand why this script doesn't end.

DynamoDB - Update or Create if not found method

In DynamoDB, how can I make an update or create if not found method if I have a hash key and a range key in my table. Below works if I have a table with only a hash key, but not for tables with a hash and range key:
var save = function(user_id, store_id, callback){
var DOC = require('dynamodb-doc'),
docClient = new DOC.DynamoDB();
var params = {
TableName: 'stores',
ReturnValues: 'NONE',
Key: {
'user_id': user_id
},
ConditionExpression: "#a = :store_id_val",
UpdateExpression: 'SET #a = :store_id_val',
ExpressionAttributeNames: {
'#a': 'store_id'
},
ExpressionAttributeValues: {
':store_id_val': store_id
}
};
// Save DynamoDB Document
docClient.updateItem(params, function(error, response) {
return callback(error, response);
});
}
It is simple. I just need to specify both hash and range key in the Key parameter. Then I can get away with this:
var save = function(user_id, store_id, callback) {
var DOC = require('dynamodb-doc'),
docClient = new DOC.DynamoDB();
var params = {
TableName: 'stores',
ReturnValues: 'NONE',
Key: {
'user_id': user_id,
'store_id': store_id
}
};
// Save DynamoDB Document
docClient.updateItem(params, function(error, response) {
return callback(error, response);
});
}

Categories