Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GetItem from Secondary Index with DynamoDB

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

like image 607
pedalpete Avatar asked May 02 '17 07:05

pedalpete


People also ask

How do I get DynamoDB GetItem?

Retrieving an item in DynamoDB requires using GetItem, and specifying the table name and item primary key. Be sure to include a complete primary key rather than omitting a portion. For example, omitting the sort key of a composite key. It executes as an eventually consistent read.

How do secondary indexes work DynamoDB?

DynamoDB supports two types of secondary indexes: Global secondary index — An index with a partition key and a sort key that can be different from those on the base table. A global secondary index is considered "global" because queries on the index can span all of the data in the base table, across all partitions.

Why would you use a secondary index on a DynamoDB table?

Secondary indexes are a critical part of modeling your data in DynamoDB. With a secondary index, you can add additional access patterns to your application without the hassle of maintaining multiple copies of the same data. DynamoDB will handle all replication from the base table to your secondary index.


1 Answers

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", "[email protected]", "john", "key1") // OK account.putItem("1", "[email protected]", "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", "[email protected]", "john", "key1") // OK account.putItem("1", "[email protected]", "john", "key1") // OK 

i.e.

// assume dummy api putItem(id, email, name, apiKey) account.putItem("1", "[email protected]", "john", "key1") // OK account.putItem("2", "[email protected]", "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.

like image 147
Oh Chin Boon Avatar answered Sep 18 '22 14:09

Oh Chin Boon