Skip to content

Dynamodb get a single item based on sort key only

I am new to dynamodb and I need to process 5M records. Each record has an id and a status. I need to query for each record based on its status, process it, and finally update the status.

I am using DynamoDbEnhancedClient but I could not find example on how to query based only on the range and not the hash, while avoiding scan. I tried to create a query with a condition and a limit of 1 but it did not work.

Here is what I have:

My Customer model:

private String id;
@DynamoDbSecondarySortKey(indexNames = "status")
private String status;
private String name;


public DynamoDbEnhancedClient dynamoDbEnhancedClient(){
    return DynamoDbEnhancedClient.builder()

My query:

static final TableSchema<Customer> CUSTOMER_TABLE = TableSchema.fromClass(Customer.class);

public Customer findByStatus() {
    DynamoDbTable<Customer> customerTable = dynamoDbEnhancedClient.table("customer", CUSTOMER_TABLE);

    QueryConditional queryConditionalPerPartition = new EqualToConditional(Key.builder().

    QueryEnhancedRequest request = QueryEnhancedRequest.builder()

    PageIterable<Customer> pageIterable = customerTable.query(request);

    Customer customer =;
    return customer;

However that does not work. How can query by status and only get a single result? I have no restriction on the table structure and I can change it however I require.



So I finally figured it out, I needed to create create a GSI (Global Secondary Index)

When creating the GCI you define the the sort key as hash key and than you can query the index.

create table:

aws dynamodb create-table 
--table-name customer 
--table-class STANDARD 
--global-secondary-index '[
  "IndexName": "id-status",
  "KeySchema": [
       "AttributeName": "status",
      "KeyType": "HASH"
       "AttributeName": "id",
      "KeyType": "RANGE"
  "Projection": {
    "ProjectionType": "ALL"
  "ProvisionedThroughput": {
    "ReadCapacityUnits": 1,
    "WriteCapacityUnits": 1

My model in Java:

public class Customer {

private String id;
private String status;
private Instant created;
private Instant updated;

public Customer(){

@DynamoDbSecondarySortKey(indexNames = "id-status")
public String getId() {
    return id;

@DynamoDbSecondaryPartitionKey(indexNames = "id-status")
public String getStatus() {
    return status;

@DynamoDBTypeConverted(converter = InstantToStringTypeConverter.class)
public Instant getCreated() {
    return created;

@DynamoDBTypeConverted(converter = InstantToStringTypeConverter.class)
public Instant getUpdated() {
    return updated;

Than query the db:

public class customerDAO {

static final TableSchema<customer> CUSTOMER_TABLE = 

private DynamoDbEnhancedClient dynamoDbEnhancedClient;

public Customer findByStatus() {

    DynamoDbTable<Customer> customerTable = dynamoDbEnhancedClient.table("customer", CUSTOIMER_TABLE);

    DynamoDbIndex<Customer> secIndex = customerTable.index("id-status");

    QueryConditional queryConditional = QueryConditional

    PageIterable<Customer> results =
            (PageIterable<Customer>) secIndex.query(QueryEnhancedRequest.builder().
    results.forEach(p -> p.items().forEach(item -> System.out.println(customer)));

2 People found this is helpful