Query More Than 100 DynamoDB Items that match a Partition Key using Java SDK 2?

2.4k views Asked by At

How can more than 100 items from a dynamodb table, matching a particular partition key, be queried using aws java sdk 2?

If the number of rows that match a hash key exceeds 100 then the batchGetItemPaginator method needs to be used. This method accepts a BatchGetItemRequest which requires a KeysAndAttributes.

When I construct a KeysAndAttributes with just a hash key, but not a sort key, I get the following exception

DynamoDbException: The provided key element does not match the schema

However, if I provide a sort key in the KeysAndAttributes then the batchGetItemPaginator method works fine.

So how can a BatchGetItemRequest be constructed with just a primary key (no sort key)?

Note: my question is not a duplicate of this question. That other question does not involve the required pagination if the number of rows exceeds 100.

Thank you in advance for your consideration and response.

2

There are 2 answers

2
Balu Vyamajala On BEST ANSWER

Primary key >> Partition + HashKey

GetItem is used to get one item by primary key.

BatchGetItem is used to get multiple items from multiple tables using multiple primary keys. so, we need to pass list of Partition & HashKey

We can never do a getItem or batchGetItem with partial key i.e just Partition Key.

To fetch items just by partition key, we must use query api, which returns maximum of 1 MB of data. To fetch all the records with a particular partition key, we can paginate by calling query api multiple times with exclusiveStartKey

.exclusiveStartKey(exclusiveStartKey) helps us to start after a particular record.

.limit(10) usually set to a reasonable number that doesn't exceed total size beyond 1 MB. if no of items is not a concern, we can exclude this.

response.lastEvaluatedKey() capture this from the response to be used for next query.

public static Map<String, AttributeValue> queryTable(DynamoDbClient ddb, String tableName, String partitionKeyName,
        String partitionKeyVal, Map<String, AttributeValue> exclusiveStartKey) {

    Map<String, AttributeValue> lastEvaluatedKey = null;

    HashMap<String, AttributeValue> attrValues = new HashMap<String, AttributeValue>();
    attrValues.put(":" + partitionKeyName, AttributeValue.builder().s(partitionKeyVal).build());
    QueryRequest queryReq = QueryRequest.builder().tableName(tableName).exclusiveStartKey(exclusiveStartKey)
            .keyConditionExpression(partitionKeyName + " = :" + partitionKeyName)
            .expressionAttributeValues(attrValues).limit(10).build();

    try {
        QueryResponse response = ddb.query(queryReq);
        lastEvaluatedKey = response.lastEvaluatedKey();
    } catch (DynamoDbException e) {
        System.err.println(e.getMessage());
        System.exit(1);
    }
    return lastEvaluatedKey;
}

sample test on table test with pk as partition key for value 1

public static void main(String[] args) {

    Region region = Region.US_EAST_1;
    DynamoDbClient ddb = DynamoDbClient.builder().region(region).build();

    Map<String, AttributeValue> lastEvaluatedKey = null;
    // Loop until we don't get lastEvaluatedKey 
    do {
        System.out.println("---------DynamoDb Query with Exclusive Start Key------------" + lastEvaluatedKey);
        lastEvaluatedKey = queryTable(ddb, "test", "pk", "1", lastEvaluatedKey);
    } while (lastEvaluatedKey != null && !lastEvaluatedKey.isEmpty());

    ddb.close();
}
0
Bill Davis On

The accepted answer above is partially wrong (at least as of v2 of the Java SDK), you can do a batch get item with only a primary key.

Unfortunately, the code I have is proprietary therefore I can't share it but just look at the Javadocs around batch get item.

For example: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/BatchGetItemResponse.html