[database] How to get item count from DynamoDB?

I want to know item count with DynamoDB querying.

I can querying for DynamoDB, but I only want to know 'total count of item'.

For example, 'SELECT COUNT(*) FROM ... WHERE ...' in MySQL

$result = $aws->query(array(
 'TableName' => 'game_table',
 'IndexName' => 'week-point-index',
 'KeyConditions' => array(
    'week' => array(
        'ComparisonOperator' => 'EQ',
        'AttributeValueList' => array(
            array(Type::STRING => $week)
        )
    ),
    'point' => array(
        'ComparisonOperator' => 'GE',
        'AttributeValueList' => array(
            array(Type::NUMBER => $my_point)
        )
    )
 ),
));
echo Count($result['Items']);

this code gets the all users data higher than my point.

If count of $result is 100,000, $result is too much big. And it would exceed the limits of the query size.

I need help.

This question is related to database amazon-dynamodb

The answer is


In Scala:

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
import com.amazonaws.services.dynamodbv2.document.DynamoDB
val client = AmazonDynamoDBClientBuilder.standard().build()

val dynamoDB = new DynamoDB(client)
val tableDescription = dynamoDB.getTable("table name").describe().getItemCount()

Similar to Java in PHP only set Select PARAMETER with value 'COUNT'

$result = $aws->query(array(
 'TableName' => 'game_table',
 'IndexName' => 'week-point-index',
 'KeyConditions' => array(
    'week' => array(
        'ComparisonOperator' => 'EQ',
        'AttributeValueList' => array(
            array(Type::STRING => $week)
        )
    ),
    'point' => array(
        'ComparisonOperator' => 'GE',
        'AttributeValueList' => array(
            array(Type::NUMBER => $my_point)
        )
    )
 ),
 'Select' => 'COUNT'
));

and acces it just like this :

echo $result['Count'];

but as Saumitra mentioned above be careful with resultsets largers than 1 MB, in that case use LastEvaluatedKey til it returns null to get the last updated count value.


Can be seen from UI as well. Go to overview tab on table, you will see item count. Hope it helps someone.


If you happen to reach here, and you are working with C#, here is the code:

var cancellationToken = new CancellationToken();

var request = new ScanRequest("TableName") {Select = Select.COUNT};

var result = context.Client.ScanAsync(request, cancellationToken).Result;

totalCount = result.Count;

You could use dynamodb mapper query.

PaginatedQueryList<YourModel> list = DymamoDBMapper.query(YourModel.class, queryExpression);
int count = list.size();

it calls loadAllResults() that would lazily load next available result until allResultsLoaded.

Ref: https://docs.amazonaws.cn/en_us/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html#DynamoDBMapper.Methods.query


len(response['Items'])

will give you the count of the filtered rows

where,

fe = Key('entity').eq('tesla')
response = table.scan(FilterExpression=fe)

Replace the table name and use the below query to get the data on your local environment:

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT" --endpoint-url http://localhost:8000

Replace the table name and remove the endpoint url to get the data on production environment

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"

With the aws dynamodb cli you can get it via scan as follows:

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"

The response will look similar to this:

{
    "Count": 123,
    "ScannedCount": 123,
    "ConsumedCapacity": null
}

notice that this information is in real time in contrast to the describe-table api


I'm too late here but like to extend Daniel's answer about using aws cli to include filter expression.

Running

aws dynamodb scan \
    --table-name <tableName> \
    --filter-expression "#v = :num" \
    --expression-attribute-names '{"#v": "fieldName"}' \
    --expression-attribute-values '{":num": {"N": "123"}}' \
    --select "COUNT"

would give

{
    "Count": 2945,
    "ScannedCount": 7874,
    "ConsumedCapacity": null
}

That is, ScannedCount is total count and Count is the number of items which are filtered by given expression (fieldName=123).


I used scan to get total count of the required tableName.Following is a Java code snippet for same

Long totalItemCount = 0;
do{
    ScanRequest req = new ScanRequest();
    req.setTableName(tableName);

    if(result != null){
        req.setExclusiveStartKey(result.getLastEvaluatedKey());
    }

    result = client.scan(req);

    totalItemCount += result.getItems().size();

} while(result.getLastEvaluatedKey() != null);

System.out.println("Result size: " + totalItemCount);

This is solution for AWS JavaScript SDK users, it is almost same for other languages.

Result.data.Count will give you what you are looking for

 apigClient.getitemPost({}, body, {})

    .then(function(result){

        var dataoutput = result.data.Items[0];

        console.log(result.data.Count);
  }).catch( function(result){

});

I'm posting this answer for anyone using C# that wants a fully functional, well-tested answer that demonstrates using query instead of scan. In particular, this answer handles more than 1MB size of items to count.

        public async Task<int> GetAvailableCount(string pool_type, string pool_key)
    {
        var queryRequest = new QueryRequest
        {
            TableName = PoolsDb.TableName,
            ConsistentRead = true,
            Select = Select.COUNT,
            KeyConditionExpression = "pool_type_plus_pool_key = :type_plus_key",
            ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
                {":type_plus_key", new AttributeValue { S =  pool_type + pool_key }}
            },
        };
        var t0 = DateTime.UtcNow;
        var result = await Client.QueryAsync(queryRequest);
        var count = result.Count;
        var iter = 0;
        while ( result.LastEvaluatedKey != null && result.LastEvaluatedKey.Values.Count > 0) 
        {
            iter++;
            var lastkey = result.LastEvaluatedKey.Values.ToList()[0].S;
            _logger.LogDebug($"GetAvailableCount {pool_type}-{pool_key} iteration {iter} instance key {lastkey}");
            queryRequest.ExclusiveStartKey = result.LastEvaluatedKey;
            result = await Client.QueryAsync(queryRequest);
            count += result.Count;
        }
        _logger.LogDebug($"GetAvailableCount {pool_type}-{pool_key} returned {count} after {iter} iterations in {(DateTime.UtcNow - t0).TotalMilliseconds} ms.");
        return count;
    }
}