¿Cómo obtener el recuento de elementos de DynamoDB?

82

Quiero saber el recuento de elementos con las consultas de DynamoDB.

Puedo consultar DynamoDB, pero solo quiero saber el 'recuento total de elementos'.

Por ejemplo, 'SELECT COUNT (*) FROM ... WHERE ...' en 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']);

este código hace que los datos de todos los usuarios sean más altos que mi punto.

Si el recuento de $ resultado es 100.000, $ resultado es demasiado grande. Y excedería los límites del tamaño de la consulta.

Necesito ayuda.

sam lee
fuente

Respuestas:

29

Puede utilizar el Selectparámetro y utilizarloCOUNT en la solicitud. "Devuelve el número de elementos coincidentes, en lugar de los elementos coincidentes en sí". Importante , como lo mencionó Saumitra R. Bhave en un comentario , "Si el tamaño del conjunto de resultados de la consulta es superior a 1 MB, ScannedCount y Count representarán solo un recuento parcial del total de elementos. Deberá realizar varios Operaciones de consulta para recuperar todos los resultados " .

No estoy familiarizado con PHP, pero así es como se puede usar con Java. Y luego, en lugar de usar Count(que supongo que es una función en PHP) en el 'Items', puede usar el Countvalor de la respuesta - $result['Count']:

final String week = "whatever";
final Integer myPoint = 1337;
Condition weekCondition = new Condition()
        .withComparisonOperator(ComparisonOperator.EQ)
        .withAttributeValueList(new AttributeValue().withS(week));
Condition myPointCondition = new Condition()
        .withComparisonOperator(ComparisonOperator.GE)
        .withAttributeValueList(new AttributeValue().withN(myPoint.toString()))

Map<String, Condition> keyConditions = new HashMap<>();
keyConditions.put("week", weekCondition);
keyConditions.put("point", myPointCondition);

QueryRequest request = new QueryRequest("game_table");
request.setIndexName("week-point-index");
request.setSelect(Select.COUNT);
request.setKeyConditions(keyConditions);

QueryResult result = dynamoDBClient.query(request);
Integer count = result.getCount();

Si no necesita emular la WHEREcláusula, puede utilizar una DescribeTablesolicitud y utilizar el recuento de elementos resultante para obtener una estimación.

El número de elementos de la tabla especificada. DynamoDB actualiza este valor aproximadamente cada seis horas. Es posible que los cambios recientes no se reflejen en este valor.

Además, una nota importante de la documentación como señaló Saumitra R. Bhave en los comentarios sobre esta respuesta:

Si el tamaño del Queryconjunto de resultados es superior a 1 MB ScannedCounty Countrepresenta solo un recuento parcial del total de elementos. Debe realizar varias Queryoperaciones para recuperar todos los resultados (consulte Paginación de resultados de consultas de tabla ).

mkobit
fuente
17
Sin embargo, creo que hay una pequeña trampa aquí, según docs.aws.amazon.com/amazondynamodb/latest/developerguide/… que dice "Si el tamaño del conjunto de resultados de la consulta es mayor que 1 MB, entonces ScannedCount y Count representarán sólo un recuento parcial del total de elementos ", lo que básicamente significa que los elementos se recuperan primero y luego se cuentan, y si el tamaño de los elementos recuperados supera 1 MB, incluso se
paginará el
No quiero robar el trabajo original de @ mkobit, pero esta es una forma de hacerlo usando encadenamiento fluido:AmazonDynamoDBClientBuilder.standard().withRegion(region).withCredentials(credentialsProvider).build() .query(new QueryRequest(freeKeysTableName).withSelect(Select.COUNT)).getCount()
Sridhar Sarnobat
2
Solo para completar su respuesta, como se señaló, es posible que deba repetir la llamada hasta que LastEvaluateKey ya no esté presente en los resultados y esto puede verse así (llega al final del código anterior): while(result.getLastEvaluatedKey()!=null){ request.setExclusiveStartKey(result.getLastEvaluatedKey()); result = dynamoDBClient.query(request); count+= result.getCount(); }
Peter Koncz
140

Con aws dynamodb cli puede obtenerlo mediante escaneo de la siguiente manera:

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

La respuesta se verá similar a esto:

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

observe que esta información está en tiempo real en contraste con la API describe-table

Daniel Bubenheim
fuente
2
@JHH Acabo de probar esto y parece que usa unidades de capacidad de lectura. Según la consola DynamoDB, mi consulta consumió alrededor de 12 unidades (solo 1 está configurada); Supongo que está utilizando la capacidad de ráfaga para atender la consulta.
Zodman
2
@Zodman, ¡gracias por probarlo! Leí los documentos una vez más y, de hecho, encontré una declaración sobre los recuentos que me había perdido anteriormente: "Obtener el recuento de elementos utiliza la misma cantidad de unidades de capacidad de lectura y está sujeto a los mismos cálculos de tamaño de elemento, porque DynamoDB tiene que leer cada uno elemento para incrementar el recuento. " docs.aws.amazon.com/amazondynamodb/latest/developerguide/…
JHH
2
Uno podría pensar que almacenar en caché el recuento, al menos dentro de límites eventualmente consistentes, sería factible para que solo consuma una CU, pero tal vez obtener solo el recuento no es un escenario muy común.
JHH
2
@HelenNeely Sí, de esta manera proporciona el último recuento de artículos.
Daniel Bubenheim
1
Esta respuesta no es correcta, al menos en el contexto de la pregunta. La pregunta es cómo obtener un recuento de los registros que coinciden con una expresión de filtro, de ahí la comparación con la declaración WHERE. AFAIK de tratar de resolver esto durante meses es que no puede obtener un recuento de registros coincidentes. dynamoDB revisará cada registro de la tabla o índice y devolverá los que coincidan con el filtro, 1000 registros a la vez. Es posible que solo tenga 20 registros coincidentes y obtendrá 20 como recuento. Sin embargo, puede haber 40 en los siguientes 1000 registros, y así sucesivamente.
Chris Love
22

También se puede ver desde la interfaz de usuario. Vaya a la pestaña de descripción general en la tabla, verá el recuento de artículos. Espero que ayude a alguien.

coder007
fuente
6
Sí, pero tiene limitaciones: "El tamaño del almacenamiento y el recuento de elementos no se actualizan en tiempo real. Se actualizan periódicamente, aproximadamente cada seis horas".
matthias
Además, si queremos ver el recuento de una consulta, no se puede hacer en la pestaña Descripción general. Solo muestra el total de filas en la tabla, no el recuento del conjunto de resultados de mi consulta.
Jyotsana Nandwani
7

Reemplace el nombre de la tabla y use la siguiente consulta para obtener los datos en su entorno local:

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

Reemplace el nombre de la tabla y elimine la URL del punto final para obtener los datos en el entorno de producción

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"
Ravi Ranjan
fuente
6

Si llega aquí y está trabajando con C #, aquí está el código:

var cancellationToken = new CancellationToken();

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

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

totalCount = result.Count;
ymerej
fuente
Esto no funciona si tiene más de 1 MB de elementos.
JohnOpincar
1

Similar a Java en PHP solo establezca Seleccione PARÁMETRO con valor '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'
));

y acceda así:

echo $ resultado ['Recuento'];

pero como Saumitra mencionó anteriormente, tenga cuidado con los conjuntos de resultados de más de 1 MB, en ese caso use LastEvaluateKey hasta que devuelva nulo para obtener el último valor de recuento actualizado.

Jajhonrod
fuente
0
len(response['Items'])

le dará el recuento de las filas filtradas

dónde,

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

Estoy publicando esta respuesta para cualquiera que use C # y quiera una respuesta completamente funcional y bien probada que demuestre el uso de consultas en lugar de escanear. En particular, esta respuesta maneja más de 1 MB de tamaño de elementos para contar.

        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;
    }
}
JuanOpincar
fuente
-1

En 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()
Joshua David Lickteig
fuente
-2

Usé escanear para obtener el recuento total de tableName requerido. A continuación, se muestra un fragmento de código Java para el mismo

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);
user1977823
fuente
-5

Esta es la solución para los usuarios de AWS JavaScript SDK, es casi la misma para otros idiomas.

Result.data.Count le dará lo que está buscando

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

    .then(function(result){

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

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

});
Mustafa Kahraman
fuente
2
Incluya una explicación con su respuesta.
WonderWorker