Paul Chuang
Paul Chuang

Reputation: 281

DynamoDB V2 Enhanced SDK to get only one record matching a partition key

import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

private static DynamoDbTable<MyFooEntity> table;

public MyFooEntity getOneItemByPartitionKey(String partitionKey) {
    AttributeValue pk = AttributeValue.builder().s(partitionKey).build();
    Key key = Key.builder().partitionValue(partitionKey).build();
    QueryConditional queryCond = QueryConditional.keyEqualTo(key);
    List<MyFooEntity> fooList = table.query(queryCond).items().stream().collect(Collectors.toList());
    return fooList.size() > 0 ? fooList.get(0) : null;
}

I tried to limit the query result but it did not work and same amount of records (100,000) would be returned.

List<MyFooEntity> fooList = table.query(r -> r.queryConditional(queryCond).limit(1)).items().stream().collect(Collectors.toList());
    return resultList;
}

I hope to do a query that, as soon as the first record with the same partition key is found, the result list is returned.

Upvotes: 0

Views: 260

Answers (2)

Paul Chuang
Paul Chuang

Reputation: 281

Following the concept of @Leeroy Hannigan, you can query from DynamoDB and get Iterator<Page<MyFooEntity>> object with 1 item in each page. Then, just get the first item from the first page if it exists. The query performance has improved and query is as fast regardless of how many items matching the partition key.

import java.util.Iterator;

import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.model.Page;
import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

private static DynamoDbTable<MyFooEntity> table;

public MyFooEntity getOneItemByPartitionKey(String partitionKey) {
    AttributeValue pk = AttributeValue.builder().s(partitionKey).build();
    Key key = Key.builder().partitionValue(partitionKey).build();
    QueryConditional queryCond = QueryConditional.keyEqualTo(key);
    Iterator<Page<MyFooEntity>> results = table.query(r -> r.queryConditional(queryCond).limit(1)).iterator();
    if (results.hasNext()) {
        Page<MyFooEntity> page = results.next();
        if (!page.items().isEmpty()) {
            return page.items().get(0);
        }
    }
    return null;
}

Upvotes: 0

Leeroy Hannigan
Leeroy Hannigan

Reputation: 19813

By default Query will try to read all items that match the KeyConditionExpression. Where you have set a limit, it actually limits the page size returned.

You need to set a limit on the iterator, to basically tell it to fetch only 1 page.

table.query(queryCond).items().stream().limit(1).collect(Collectors.toList())

Upvotes: 0

Related Questions