- Newest
- Most votes
- Most comments
To do a BatchGetItem you need to use the full primary key of the base table, that means that your base table should have a schema of :
| PK | SK |
|---|---|
| CustomerId | OrderId |
This is because LSI's do not allow doing GetItem because GetItem requires every item to be unique and items in an LSI are not guaranteed to be unique. For that reason, you must use Query against an LSI.
One problem with that is that there is no BatchQuery operation. But doing a Query like the following will work:
-
Get all customer orders
SELECT * FROM mytable.mylsi WHERE CustomerId = 'foo' -
Get all customer orders where sort key begins with 'bar'
SELECT * FROM mytable.mylsi WHERE CustomerId = 'foo' AND orderId begins_with('bar')
The approach you're currently using with BatchGetItem is not the most appropriate for retrieving multiple items based on a partition key and multiple LSI (Local Secondary Index) sort keys. BatchGetItem is designed to retrieve items with specific primary keys across one or more tables, but it doesn't support querying based on LSI sort keys.
For your use case, where you need to retrieve multiple items using a partition key and many values of the LSI key, the recommended approach is to use the Query operation. Here's how you can modify your code to achieve this using the AWS SDK for Java v2:
- First, create a QueryConditional for the partition key:
QueryConditional queryConditional = QueryConditional.keyEqualTo(Key.builder() .partitionValue(partitionKey) .build());
- Then, create a QueryEnhancedRequest with the conditional and specify the LSI:
QueryEnhancedRequest queryEnhancedRequest = QueryEnhancedRequest.builder() .queryConditional(queryConditional) .index("your-lsi-name") // Replace with your actual LSI name .build();
- Execute the query and process the results:
DynamoDbTable<Customer> customerTable = dynamoDbEnhancedClient.table(CUSTOMER_TABLE, CUSTOMER_SCHEMA); PageIterable<Customer> results = customerTable.query(queryEnhancedRequest); for (Page<Customer> page : results) { for (Customer customer : page.items()) { // Process each customer } }
This approach allows you to retrieve all items with the specified partition key that match any of the LSI sort key values in a single query operation. The Query operation is more efficient for this use case as it can retrieve multiple items that share the same partition key.
If you need to filter the results further based on the LSI sort key values, you can add a filter expression to the QueryEnhancedRequest:
String filterExpression = "physicalField IN (:values)"; Map<String, AttributeValue> expressionValues = new HashMap<>(); expressionValues.put(":values", AttributeValue.builder().ss(lsiSortKeys).build()); QueryEnhancedRequest queryEnhancedRequest = QueryEnhancedRequest.builder() .queryConditional(queryConditional) .index("your-lsi-name") .filterExpression(filterExpression) .expressionValues(expressionValues) .build();
This approach will be more efficient and appropriate for retrieving multiple items based on a partition key and multiple LSI sort key values using the AWS Java DynamoDB SDK V2.
Sources
Perform batch operations - AWS SDK for Java 2.x
DynamoDB API - Amazon DynamoDB
Partitions and data distribution in DynamoDB - Amazon DynamoDB

My table structure is as per below
CustomerId (Partition Key) | EmailId (SortKey) | OrderId (LSI Field) |
I am able to make the BatchGetItem request using customerId and EmailId. However, when I am trying to do the same using CustomerId and the OrderId the request fails with 400 error
Ok, I get your question. Updated answer.
@Leeroy Thanks for the answer. However, OrderId is UUID. I could perform IN operation with a batch of 50. I am unsure what the cost implication of IN operation would be compared to ReadBatch with sort key even though IN operation will be performed on the index key.