I have a table in Dynamodb and I'm trying to get an item (using docClient.get) by naming a Global Secondary Index but I'm getting the error:
The provided key element does not match the schema
And here's my query:
docClient
.get({
TableName: 'table',,
IndexName: 'gsi_table',
Key: { primary_key }
})
But then I looked at the get documentation and it does not have an IndexName property. So I thought maybe I should name the GSI instead of the table name:
docClient
.get({
TableName: 'gsi_table',
Key: { primary_key }
})
But then I faced:
Requested resource not found
which means gsi_table is not recognized as a global table. So my question is, having the list of operations:
batchGet
batchWrite
createSet
delete
get
put
query
scan
update
which ones support GSI and LSI? And also, if you want to retrieve one specific item using a GSI, which operation should you use? If I use query, am I actually doing things as fast/cheap as possible?
Secondary indexes are for Query and Scan operations only. So, if you must use a global (or local) secondary index, then Query would be faster than Scan, of course.
To access your "single" item, you can use data.Items[0]. For example:
const params = {
TableName: "TABLE_NAME",
IndexName: "INDEX_NAME",
KeyConditionExpression: "INDEX_KEY = :k",
ExpressionAttributeValues: {
":k": some_value
}
};
docClient.query(params, (err, data) => {
if (err) {
console.log(err);
} else {
const myItem = data.Items[0];
}
});
Related
I'm trying to update an Item in my Dynamodb Table +Users+. I have tried many different ways but I always received the same error message:
The provided key element does not match the schema
The creation of an Item works, as well as a query but not the update. When I check on DynamoDB the user is well created:
{
"email": "test#email.com",
"password": "123",
"registration": 1460136902241,
"verified": false
}
Here is the table information:
Table name: Users
Primary partition key: email (String)
Primary sort key: registration (Number)
Here is the code (called from lambda):
exports.handler = function(event, context)
{
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "Users",
Item:{
email: "test#email.com",
password: "123",
verified: false,
registration: (new Date()).getTime(),
}
};
// Create the user.
docClient.put(params, function(err, data)
{
if (err)
{
context.fail("Put failed...");
return;
}
var params = {
TableName: "Users",
Key: { email : "test#email.com" },
AttributeUpdates: {
verified: {
Action: "PUT",
Value: true
}
}
};
// Update the user.
docClient.update(params, function(err, data)
{
if (err)
{
console.log(JSON.stringify(err));
context.fail(JSON.stringify(err));
return;
}
context.succeed("User successfully updated.");
});
});
};
Do you have any idea of what could be wrong in my code?
You are only providing half of your primary key. Your primary key is a combination of the partition key and range key. You need to include the range key in your Key attribute in the update parameters.
For others who have faced the same challenge and the issue is not fixed by above answers, it is always better to double check the data type of the value being updated, in my case the primary key was expecting a Number and I was trying to update with a string. Silly me
My issue was with the Node SDK for deletes, where the documentation says to provide in format:
... {Key: {'id': {S: '123'}}} ...
Which does not appear to work with the aws-sdk ^2.1077.0. This seems to work:
... {Key: {'id': '123'}} ...
My checklist when facing this issue:
Check that the name and type of your key correspond to what you have in the database.
Use corresponding attributes to make it explicit. E.g. use #DynamoDBHashKey(attributeName = "userId") in Java to indicate the partition key named userId.
Ensure that only one field or getter marked as partition key in your class.
Please, add more if you know in the comments.
I was doing BatchGetItem, then streamed it to BatchWriteItem (Delete). DeleteItem didn't like it got all attributes from the object instead of only partition and sort key.
Gathering all answers:
mismatch in an attribute name
mismatch in attribute type
half key provided
unnecessary additional keys
I have the following table in my DynamoDB
Thread (id, userId, content)
With id being the primary key. I have not defined any sort key.
Now i need to retrieve a result based on the userId .. in short i need all the records in table containing a specific userId
userId = '123';
let queryParams = {
TableName: tableName,
ExpressionAttributeNames: {
'#userid': 'userid'
},
ExpressionAttributeValues: {
':userid': userId
},
KeyConditionExpression: "#userid = :userid"
}
dynamodb.query(queryParams, (err, data) => {
console.log(err);
console.log(data);
});
when i run this, i get an error
Could not load items: ValidationException: Query condition missed key schema element: id
Can someone please let me know how can i query for all records containing the userId '123'??
To do this, you will need to add a Global Secondary Index to your table that has userId as the primary key. Then you can query that index directly.
You must also include the name of the index in the query request (source).
When I tried to update a item in dynamodb the following error appears:
var docClient = new AWS.DynamoDB.DocumentClient();
function updateItem() {
var table = "Bicycle";
var params = {
TableName:table,
Key:{
warrantyDate: "2018/10/23",
warrantyStatus: "Active"
},
UpdateExpression: "set warrantyStatus = :r",
ExpressionAttributeValues:{
":r":"Inactive"
},
ReturnValues:"UPDATED_NEW"
};
docClient.update(params, function(err, data) {
if (err) {
alert("Unable to update item");
alert(err);
} else {
alert("UpdateItem succeeded");
}
});
}
when I call this function I received this exception:
ValidationException: The provided key element does not match the schema
how can i fix this?
The problem is that you KEY attribute value does not match your primary partition key on your dynamodb table.
When updating an item, you need to specify the single key that maps to your primary key on the dynamodb table. There should only be one attribute in the Key field. You are trying to find a key that is both the warrantyDate and warrantyStatus. Make sure you're specifying the correct key that maps to your dynamodb configuration.
If you're trying to update multiple items, you need to use another function, as doClient.update() only updates a single row that matches your key to the primary index on the table.
Is it possible to do batch write to DynamoDB (using the Java SDK v1.11.1 with the document API) while using the value of a global secondary index as a conditional expression?
For example, I'd like to issue a batch update request that would update the attributes A, B and C for any items where the GSI MyIndex is equal to some value.
Is this possible, or do I have to do a query on the GSI and use the resulting primary keys for the batch write?
Few things:
Queries must be against a Table/Index's Primary Key (so no joining on a GSI)
To the best of my knowledge you can't add ConditionalExpressions to batchWriteItem.
batchWriteItem can't update. (see first note here)
I'd do something like this:
// Get keys from GSI
dynamodb.query({
IndexName: 'index',
TableName: 'table',
KeyConditionExpression: 'some expression',
}, (error, rows) =>
// Spin up a bunch of update requests
Promise.all(rows.Items.map((row) => dynamodb.update({
ExpressionAttributeValues: {
':aVal': 'new value for a',
':bVal': 'etc',
':cVal': 'etc',
},
IndexName: 'index',
Key: {
primaryKey: row.primaryKey,
},
KeyConditionExpression: 'primaryKey = :primKey',
UpdateExpression: 'set a = :aVal, b = :bVal, c = :cVal',
}).promise())));
BatchWriteItem does not behave in the same way as individual PutItem and DeleteItem calls would. For example, you cannot specify conditions on individual put and delete requests.
see docs
I'm trying to update an Item in my Dynamodb Table +Users+. I have tried many different ways but I always received the same error message:
The provided key element does not match the schema
The creation of an Item works, as well as a query but not the update. When I check on DynamoDB the user is well created:
{
"email": "test#email.com",
"password": "123",
"registration": 1460136902241,
"verified": false
}
Here is the table information:
Table name: Users
Primary partition key: email (String)
Primary sort key: registration (Number)
Here is the code (called from lambda):
exports.handler = function(event, context)
{
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "Users",
Item:{
email: "test#email.com",
password: "123",
verified: false,
registration: (new Date()).getTime(),
}
};
// Create the user.
docClient.put(params, function(err, data)
{
if (err)
{
context.fail("Put failed...");
return;
}
var params = {
TableName: "Users",
Key: { email : "test#email.com" },
AttributeUpdates: {
verified: {
Action: "PUT",
Value: true
}
}
};
// Update the user.
docClient.update(params, function(err, data)
{
if (err)
{
console.log(JSON.stringify(err));
context.fail(JSON.stringify(err));
return;
}
context.succeed("User successfully updated.");
});
});
};
Do you have any idea of what could be wrong in my code?
You are only providing half of your primary key. Your primary key is a combination of the partition key and range key. You need to include the range key in your Key attribute in the update parameters.
For others who have faced the same challenge and the issue is not fixed by above answers, it is always better to double check the data type of the value being updated, in my case the primary key was expecting a Number and I was trying to update with a string. Silly me
My issue was with the Node SDK for deletes, where the documentation says to provide in format:
... {Key: {'id': {S: '123'}}} ...
Which does not appear to work with the aws-sdk ^2.1077.0. This seems to work:
... {Key: {'id': '123'}} ...
My checklist when facing this issue:
Check that the name and type of your key correspond to what you have in the database.
Use corresponding attributes to make it explicit. E.g. use #DynamoDBHashKey(attributeName = "userId") in Java to indicate the partition key named userId.
Ensure that only one field or getter marked as partition key in your class.
Please, add more if you know in the comments.
I was doing BatchGetItem, then streamed it to BatchWriteItem (Delete). DeleteItem didn't like it got all attributes from the object instead of only partition and sort key.
Gathering all answers:
mismatch in an attribute name
mismatch in attribute type
half key provided
unnecessary additional keys