I have the following schema where I am basically just trying to have a table with id
as primary key, and both code
and secondCode
to be global secondary indexes to use to query the table.
resource "aws_dynamodb_table" "myDb" {
name = "myTable"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
attribute {
name = "code"
type = "S"
}
attribute {
name = "secondCode"
type = "S"
}
global_secondary_index {
name = "code-index"
hash_key = "code"
projection_type = "ALL"
}
global_secondary_index {
name = "second_code-index"
hash_key = "secondCode"
projection_type = "ALL"
}
}
When I try to look for one item by code
const toGet = Object.assign(new Item(), {
code: 'code_456',
});
item = await dataMapper.get<Item>(toGet);
locally I get
ValidationException: The number of conditions on the keys is invalid
and on the deployed instance of the DB I get
The provided key element does not match the schema
I can see from the logs that the key
is not being populated
Serverless: [AWS dynamodb 400 0.082s 0 retries] getItem({ TableName: 'myTable', Key: {} })
Here is the class configuration for Item
@table(getEnv('MY_TABLE'))
export class Item {
@hashKey({ type: 'String' })
id: string;
@attribute({
indexKeyConfigurations: { 'code-index': 'HASH' },
type: 'String',
})
code: string;
@attribute({
indexKeyConfigurations: { 'second_code-index': 'HASH' },
type: 'String',
})
secondCode: string;
@attribute({ memberType: embed(NestedItem) })
nestedItems?: Array<NestedItem>;
}
class NestedItem {
@attribute()
name: string;
@attribute()
price: number;
}
I am using https://github.com/awslabs/dynamodb-data-mapper-js
2
Answers
The issue you are facing is due to calling a
GetItem
on an index, which is not possible. AGetItem
must target a single item and an index can contain multiple items with the same key (unlike the base table), for this reason you can only use multi-item APIs on an index which areQuery
andScan
.I looked at the repo you linked for the package, I think you need to use the
.query(...)
method with theindexName
parameter to tell DynamoDB you want to use that secondary index. Usuallly in DynamoDB,get
operations use the default keys (in your case, you’d useget
for queries onid
, andquery
for queries on indices).Checking the docs, it’s not very clear – if you look at the
GetItem
reference, you’ll see there’s nowhere to supply an index name to actually use the index, whereas theQuery
operation allows you to supply one. As for why you need to query this way, you can read this: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html