GetItem from Secondary Index with DynamoDB

amazon-dynamodb

Solution

I guess its not so clear from the official docs. You may perform `Scan` or `Query` operation on `GSI` index, but not the `GetItem` operation.

For every record / item in a `Table`, they must have unique `HASH` and `RANGE` keys.

i.e.

// assume dummy api putItem(id, email, name, apiKey)
account.putItem("1", "abc@email.com", "john", "key1") // OK
account.putItem("1", "abc@email.com", "john", "key1") // NOT OK, id and email are table HASH and RANGE keys, must be unique

But for `Index`'es, `Hash` and `Range` keys are not unique, they may contain duplicated records / items.

i.e.

// assume dummy api putItem(id, email, name, apiKey)
account.putItem("1", "abc@email.com", "john", "key1") // OK
account.putItem("1", "bcd@email.com", "john", "key1") // OK

i.e.

// assume dummy api putItem(id, email, name, apiKey)
account.putItem("1", "abc@email.com", "john", "key1") // OK
account.putItem("2", "abc@email.com", "john", "key1") // OK

Java

http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/Index.html

`Index` implements `QueryApi` and `ScanApi` but not `GetItemApi`.

JavaScript

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#getItem-property

`GetItem` does not accept `IndexName` as a parameter.

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#query-property

`Query` accepts `IndexName` as a parameter.

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#scan-property

`Scan` accepts `IndexName` as a parameter.

Problem

I'm just getting started using DynamoDB and have setup an 'accounts' table. I've set-up a secondary index so I can query an api user and user key. Neither of these values are the primary key, as they are both volatile and can be changed. The Table is built with ``` TableName: "Accounts", KeySchema: [ { AttributeName: "id", KeyType: "HASH" }, { AttributeName: "email", KeyType: "RANGE" } ], AttributeDefinitions: [ { AttributeName: "id", AttributeType: "S" }, { AttributeName: "email", AttributeType: "S" } ] ``` And the Index is ``` TableName: 'Accounts', AttributeDefinitions: [ {AttributeName: 'name', AttributeType: 'S'}, {AttributeName: 'apiKey', AttributeType: 'S'} ], GlobalSecondaryIndexUpdates: [ { Create: { IndexName: "ApiAccounts", ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }, KeySchema: [ {AttributeName: 'name', KeyType: "HASH"}, {AttributeName: 'apiKey', KeyType: "STRING"} ], Projection: { ProjectionType: "KEYS_ONLY" }, ``` I'm now trying to get a uses account by querying the `ApiAccounts` index. I'm trying ``` dynamoClient.get({ TableName: 'Accounts', IndexName: 'ApiAccounts', Key: { name: nameKeyArray[0], apiKey: nameKeyArray[1] }, callback) ``` But I am getting an error `One of the required keys was not given a value`, which leads me to believe I can't do a 'get' on a Index? Or I'm not referring the index properly. Can somebody clarify for me? Name and API Key are unique, so I think I want to avoid a query or scan if possible

Original source