DynamoDB: Query on columns not present in the Schema - amazon-web-services

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).

Related

Trying to update DynamoDB item, what does this error mean? (I'm using Python/Boto3) [duplicate]

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

How to serverside order/sort query results in amplify-cli

I'm writing a facebook wall like function for my webapp with amplify-cli and vue, and I need to do a simple serverside orderby/sort in my query. It seems impossible..
I have tried the standard graphql way, with adding sort, it does not work...
The query generated by amplify-cli:
query ListWallposts(
$filter: ModelWallpostFilterInput
$limit: Int
$nextToken: String
) {
listWallposts(filter: $filter, limit: $limit, nextToken: $nextToken
) {
items {
id
content
createdAt
comments {
nextToken
}
user {
id
firstname
lastname
}
}
nextToken
}
}
My addition:
query ListWallposts(
$filter: ModelWallpostFilterInput
$limit: Int
$nextToken: String
) {
listWallposts(filter: $filter, limit: $limit, nextToken: $nextToken,sort:{ field:createdAt, order:ASC }
) {
items {
id
content
createdAt
comments {
nextToken
}
user {
id
firstname
lastname
}
}
nextToken
}
}
I can not add primary sortkey to dynamoDB, after amplify-cli table creation.
I have spent days trying to figure this simple thing out... Any help would be very welcome.
DynamoDB needs a global secondary index. The #key transform (or directive) can be added to your schema.graphql file as a sibling to the already existing #model transform.
Key Directive Documentation
Regarding the definition below:
directive #key(fields: [String!]!, name: String, queryField: String) on OBJECT
The important thing is that the first element of the "fields" argument is the partition (or hash) key. Every subsequent element is a sort key. Together, the sort keys will determine the order or the returned results.
(Doing so with cause amplify push to create an entirely new GraphQL field on the Query type. The value of queryField will be the new field name. The name argument is the global secondary index name.)

AWS: When I tried to update a item in dynamodb the following error appears The provided key element does not match the schema

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.

How to retreive one single item using Global Secondary Index in Dynamodb?

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];
}
});

DynamoDB - Key element does not match the schema

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