Skip to content

DynamoDB GSI Example

Ben Cook edited this page Oct 20, 2016 · 2 revisions

This is an example showing how to use spring-data-dynamodb to create a domain model and a repository class that will perform query's on a global secondary index. We will build on the example provided in the DynamoDB Hash Key Example which creates a DynamoDB table that stores customer information for a shopping cart system. It is a good idea to read through that example first.

Dynamo DB Table

We already have a table that has a unique identifier, an email address, and both the first and last name of the customer. We can already find a customer by their unique identifier, but we would want to search for a customer based upon their email address. Let's modify the table definition so that it includes a GSI on the emailAddress field.

{
  "AttributeDefinitions": [
    {
      "AttributeName": "id",
      "AttributeType": "S"
    },
    {
      "AttributeName": "emailAddress",
      "AttributeType": "S"
    },
    {
      "AttributeName": "firstName",
      "AttributeType": "S"
    },
    {
      "AttributeName": "lastName",
      "AttributeType": "S"
    }
   ],
  "KeySchema": [
    {
      "AttributeName": "id",
      "KeyType": "HASH"
    }
  ],
  "ProvisionedThroughput": {
    "ReadCapacityUnits": "10",
    "WriteCapacityUnits": "10"
  },
  "GlobalSecondaryIndexes": [
    {
        "IndexName": "idx_global_emailAddress",
        "KeySchema": [
            {
                "AttributeName": "emailAddress",
                "KeyType": "HASH"
            }
        ],
        "Projection": {
            "ProjectionType": "ALL"
        },
        "ProvisionedThroughput": {
            "ReadCapacityUnits": 10,
            "WriteCapacityUnits": 10
        }
    }
  ],
  "TableName": "customer"
}

Domain Model

The definition above translates pretty simply into a domain model object like this:

@DynamoDBTable( tableName = "customer" )
public class Customer {

	@Id
    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
	private String id;

	@DynamoDBIndexHashKey(globalSecondaryIndexName = "idx_global_emailAddress")
	private String emailAddress;

	private String firstName;
	private String lastName;

	public Customer(String id, String emailAddress, String firstName, String lastName) {
		this.id = id;
		this.emailAddress = emailAddress;
		this.firstName = firstName;
		this.lastName = lastName;
	}

	public String getId() {
		return id;
	}

	public String setId(String id) {
		this.id = id;
	}

	public String getEmailAddress() {
		return emailAddress;
	}

	public String setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}

	public String getFirstName() {
		return firstName;
	}

	public String setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public String setLastName(String lastName) {
		this.lastName = lastName;
	}
}

The only difference from the previous example is the addition of the @DynamoDBIndexHashKey annotation on the emailAddress field which indicates the name of the index in the DynamoDB table.

Repository

Finally, we will add a new method to the CustomerRepository class using the spring-data "findBy" formatting to indicate which fields to search upon. Here is what the CustomerRepository class looks like now:

public interface CustomerRepository extends CrudRepository<Customer, String> {
	public List<Customer> findByEmailAddress(String emailAddress);
}

When spring-data-dynamodb is invoked through spring-data it will search for the @DynamoDBIndexHashKey annotation on the emailAddress field. When it finds it with an index name it will create and send a Query request to DynamoDB. Spring-data-dynamodb will create and send a Scan request to DynamoDB if the @DynamoDBIndexHashKey annotation was not found and there is an @EnableScan annotation on either the CustomerRepository class or on the findbyEmailAddress method.