Ali
Ali

Reputation: 267107

'Type mismatch for Index Key' on using a sort key in DynamoDB

I have a table with the following indices:

I'd like to have is_premium be the range / sort key of expiresOn, so I could e.g query all accounts which are expiring before or on today's date, AND which have is_premium = true.

If i just queried for all accounts expiring before / on today, but without is_premium=true, I would get 90% of the table in the results.

But, if I try to set a range query on is_premium, I get the following error when I try to save a record to the table:

com.amazonaws.AmazonServiceException: Type mismatch for Index Key (Service: null; Status Code: 400; Error Code: ValidationException; Request ID: null)

at com.amazonaws.services.dynamodbv2.local.embedded.DDBExceptionMappingInvocationHandler.handleDynamoDBLocalServiceException(DDBExceptionMappingInvocationHandler.java:76) at com.amazonaws.services.dynamodbv2.local.embedded.DDBExceptionMappingInvocationHandler.invoke(DDBExceptionMappingInvocationHandler.java:58) at com.sun.proxy.$Proxy70.putItem(Unknown Source) at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.doPutItem(DynamoDBMapper.java:1270) at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$1.executeLowLevelRequest(DynamoDBMapper.java:879) at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.execute(DynamoDBMapper.java:1120) at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.save(DynamoDBMapper.java:966) at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.save(DynamoDBMapper.java:758)

I get this on dynamoDbMapper.save(order)

If I remove the sort / range key, everything works.

Any ideas what I'm doing wrong? The error is very ambigious.

Upvotes: 3

Views: 4680

Answers (2)

birnbaum
birnbaum

Reputation: 4946

Booleans are no valid hash/range key in DynamoDB. A possible solution to make the architecture you suggested work would be to modify your data mapper to map booleans on 0 and 1.

But this way you could only query for a specific expiration date and then check if the according user is premium or not. If I understood your use case correctly, what you want is all is_premium =true within a certain expiresOn timeframe. In this case the preferable architecture would be:

  • is_premium as the global secondary partition key
  • expiresOn as the global secondary sort key

This way you can query the is_premium partition and use the sort key to e.g. filter out all items in this partition that expire within one day.

Upvotes: 1

Eyal Ch
Eyal Ch

Reputation: 10056

Boolean field is not supported for hash/range keys in dynamodb. (only string/number/binary are supported).

you need to convert it to STRING or NUMBER (or to add new column). (if this will be your range key, so it can be 'true'/'false' or 0/1). if it was your hash key so it can be more complicated.

Upvotes: 6

Related Questions