Reputation: 184
I'm using serverless to create and query a DynamoDB database table, but when not querying using the primary key I get this error:
INFO Error in dynamo get ValidationException: The provided key element does not match the schema
I have another key setup as a GSI, but I still get the error.
serverless.yml
...
resources:
Resources:
BeaconTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: venue-table
AttributeDefinitions:
- AttributeName: VenueID
AttributeType: S
KeySchema:
- AttributeName: VenueID
KeyType: HASH
BillingMode: PAY_PER_REQUEST
Dynamo.js
const AWS = require('aws-sdk');
const documentClient = new AWS.DynamoDB.DocumentClient();
const Dynamo = {
async get(TableName){
const params = {
TableName,
Key:{
"BeaconAddr": <string> // Hardcoded string
}
};
const data = await documentClient
.get(params)
.promise()
if (!data || !data.Item){
throw Error(`There was an error fetching the data for ID of ${ID} from ${TableName}`)
}
console.log(data);
return data;
},
async write(data, TableName){
if (!data.ID){
throw Error('no ID on the data');
}
const params = {
TableName,
Item: data
};
const res = await documentClient.put(params).promise();
if (!res) {
throw Error(`There was an error inserting ID of ${data.ID} in table ${TableName}`)
}
return data;
}
};
module.exports = Dynamo;
The query works when the key is "VenueID", but when I change it to "BeaconAddr" (Which is a GSI) the error appears. What am I doing wrong?
Below is a diagram of the table:
Upvotes: 0
Views: 376
Reputation: 8885
A get
operation in DynamoDB is only available on the primary key of the table. Your table definition (as shown in the serverless.yml
) only includes a partition key (aka HASH), so the only way to use the get
operation is to request a single item by the key (which you have named VenueID
). If your intent is to have the sort key (aka RANGE) be the SK
attribute, and the partition key be the PK
attribute, then your table definition needs to look something like this:
BeaconTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: venue-table
AttributeDefinitions:
- AttributeName: PK
AttributeType: S
- AttributeName: SK
AttributeType: S
KeySchema:
- AttributeName: PK
KeyType: HASH
- AttributeName: SK
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
Note that there is no mention of VenueID
or BeaconAddr
in the definition. You would put the values, as you have in the display above, into those fields. To add a GSI, as you have displayed, you'd need to have this:
BeaconTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: venue-table
AttributeDefinitions:
- AttributeName: PK
AttributeType: S
- AttributeName: SK
AttributeType: S
- AttributeName: GSI-1-PK
AttributeType: S
- AttributeName: GSI-1-SK
AttributeType: S
KeySchema:
- AttributeName: PK
KeyType: HASH
- AttributeName: SK
KeyType: RANGE
GlobalSecondaryIndexes:
- IndexName: GSI-1
KeySchema:
- AttributeName: "GSI-1-PK"
KeyType: HASH
- AttributeName: GSI-1-SK
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
Note that there are separate columns here. The data that goes into those columns is up to you to populate.
Finally, when querying a GSI (you cannot get
on a GSI) you must supply the index name in the query.
Upvotes: 2