fIwJlxSzApHEZIl
fIwJlxSzApHEZIl

Reputation: 13270

DynamoDB Mapper Query Doesn't Respect QueryExpression Limit

Imagine the following function which is querying a GlobalSecondaryIndex and associated Range Key in order to find a limited number of results:

@Override
public List<Statement> getAllStatementsOlderThan(String userId, String startingDate, int limit) {

    if(StringUtils.isNullOrEmpty(startingDate)) {
        startingDate = UTC.now().toString();
    }

    LOG.info("Attempting to find all Statements older than ({})", startingDate);

    Map<String, AttributeValue> eav = Maps.newHashMap();
    eav.put(":userId", new AttributeValue().withS(userId));
    eav.put(":receivedDate", new AttributeValue().withS(startingDate));

    DynamoDBQueryExpression<Statement> queryExpression = new DynamoDBQueryExpression<Statement>()
            .withKeyConditionExpression("userId = :userId and receivedDate < :receivedDate").withExpressionAttributeValues(eav)
            .withIndexName("userId-index")
            .withConsistentRead(false);

    if(limit > 0) {
        queryExpression.setLimit(limit);
    }

    List<Statement> statementResults = mapper.query(Statement.class, queryExpression);

    LOG.info("Successfully retrieved ({}) values", statementResults.size());

    return statementResults;
}

List<Statement> results = statementRepository.getAllStatementsOlderThan(userId, UTC.now().toString(), 5);

assertThat(results.size()).isEqualTo(5); // NEVER passes

The limit isn't respected whenever I query against the database. I always get back all results that match my search criteria so if I set the startingDate to now then I get every item in the database since they're all older than now.

Upvotes: 1

Views: 1593

Answers (2)

As they've rightly answered the setLimit or withLimit functions limit the number of records fetched only in each particular request and internally multiple requests take place to fetch the results.

If you want to limit the number of records fetched in all the requests then you might want to use "Scan".

Example for the same can be found here

Upvotes: 0

Robert Balent
Robert Balent

Reputation: 1462

You should use queryPage function instead of query.

From DynamoDBQueryExpression.setLimit documentation:

Sets the maximum number of items to retrieve in each service request to DynamoDB.

Note that when calling DynamoDBMapper.query, multiple requests are made to DynamoDB if needed to retrieve the entire result set. Setting this will limit the number of items retrieved by each request, NOT the total number of results that will be retrieved. Use DynamoDBMapper.queryPage to retrieve a single page of items from DynamoDB.

Upvotes: 5

Related Questions