Wie erhalte ich die Anzahl der Artikel von DynamoDB?

79

Ich möchte die Anzahl der Elemente bei der DynamoDB-Abfrage wissen.

Ich kann nach DynamoDB fragen, möchte aber nur die Gesamtzahl der Elemente wissen.

Zum Beispiel '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']);

Dieser Code bringt die Daten aller Benutzer höher als mein Punkt.

Wenn die Anzahl von $ result 100.000 beträgt, ist $ result zu groß. Und es würde die Grenzen der Abfragegröße überschreiten.

Ich brauche Hilfe.

Sam Lee
quelle

Antworten:

27

Sie können den SelectParameter verwenden undCOUNT in der Anfrage verwenden. Es "gibt die Anzahl der übereinstimmenden Elemente zurück und nicht die übereinstimmenden Elemente selbst". Wichtig , wie von Saumitra R. Bhave in einem Kommentar angesprochen : "Wenn die Größe der Abfrage-Ergebnismenge größer als 1 MB ist, stellen ScannedCount und Count nur einen Teil der Gesamtzahl der Elemente dar. Sie müssen mehrere ausführen Abfragevorgänge, um alle Ergebnisse abzurufen " .

Ich bin nicht mit PHP vertraut, aber hier ist, wie Sie es mit Java verwenden können. Und anstatt Count(was ich vermute, ist eine Funktion in PHP) auf dem zu verwenden 'Items', können Sie den CountWert aus der Antwort verwenden - $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();

Wenn Sie die WHEREKlausel nicht emulieren müssen , können Sie eine DescribeTableAnforderung verwenden und die resultierende Elementanzahl verwenden, um eine Schätzung zu erhalten.

Die Anzahl der Elemente in der angegebenen Tabelle. DynamoDB aktualisiert diesen Wert ungefähr alle sechs Stunden. Letzte Änderungen werden möglicherweise nicht in diesem Wert berücksichtigt.

Ein wichtiger Hinweis aus der Dokumentation, wie er von Saumitra R. Bhave in den Kommentaren zu dieser Antwort erwähnt wurde:

Wenn die Größe der QueryErgebnismenge größer als 1 MB ist ScannedCountund Countnur einen Teil der Gesamtzahl der Elemente darstellt. Sie müssen mehrere QueryVorgänge ausführen , um alle Ergebnisse abzurufen (siehe Paginieren von Tabellenabfrageergebnissen ).

mkobit
quelle
16
Ich denke, dass es hier einen kleinen Haken gibt, laut docs.aws.amazon.com/amazondynamodb/latest/developerguide/…, der besagt: "Wenn die Größe der Abfrage-Ergebnismenge größer als 1 MB ist, werden ScannedCount und Count dargestellt nur eine teilweise Zählung der Gesamtzahl der Gegenstände ", was im Grunde bedeutet, dass die Gegenstände zuerst abgerufen und dann gezählt werden, und wenn die Größe der abgerufenen Gegenstände 1
MB
Ich möchte nicht @ mkobits Originalarbeit stehlen, aber dies ist eine Möglichkeit, dies mit fließender Verkettung zu tun:AmazonDynamoDBClientBuilder.standard().withRegion(region).withCredentials(credentialsProvider).build() .query(new QueryRequest(freeKeysTableName).withSelect(Select.COUNT)).getCount()
Sridhar Sarnobat
1
Um Ihre Antwort zu vervollständigen, müssen Sie den Anruf möglicherweise wiederholen, bis LastEvalencedKey nicht mehr in den Ergebnissen vorhanden ist. Dies kann folgendermaßen aussehen (bis zum Ende des obigen Codes): while(result.getLastEvaluatedKey()!=null){ request.setExclusiveStartKey(result.getLastEvaluatedKey()); result = dynamoDBClient.query(request); count+= result.getCount(); }
Peter Koncz
136

Mit dem aws dynamodb cli können Sie es wie folgt per Scan erhalten :

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

Die Antwort sieht ungefähr so ​​aus:

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

Beachten Sie, dass diese Informationen im Gegensatz zur API für die Beschreibungstabelle in Echtzeit vorliegen

Daniel Bubenheim
quelle
2
@JHH Ich habe es gerade versucht und es scheint, Lesekapazitätseinheiten zu verwenden. Laut der DynamoDB-Konsole hat meine Abfrage ungefähr 12 Einheiten verbraucht (nur 1 ist konfiguriert). Ich gehe davon aus, dass die Burst-Kapazität für die Bearbeitung der Abfrage verwendet wird.
Zodman
2
@ Zodman, danke, dass du es ausprobiert hast! Ich habe die Dokumente noch einmal durchgelesen und tatsächlich eine Aussage zu den Anzahlen gefunden, die ich zuvor verpasst habe: "Das Abrufen der Anzahl der Elemente verwendet dieselbe Anzahl von Lesekapazitätseinheiten und unterliegt denselben Berechnungen der Elementgröße, da DynamoDB jede lesen muss Element, um die Anzahl zu erhöhen. " docs.aws.amazon.com/amazondynamodb/latest/developerguide/…
JHH
2
Man könnte denken, dass das Zwischenspeichern der Zählung, zumindest innerhalb eventuell konsistenter Grenzen, möglich wäre, um nur eine einzige CU zu verbrauchen, aber vielleicht ist es kein sehr häufiges Szenario, nur die Zählung zu erhalten.
JHH
2
@HelenNeely Ja, auf diese Weise wird die neueste Artikelanzahl bereitgestellt.
Daniel Bubenheim
1
Diese Antwort ist zumindest im Zusammenhang mit der Frage nicht richtig. Die Frage ist, wie man die Anzahl der Datensätze erhält, die mit einem Filterausdruck übereinstimmen, daher der Vergleich mit der WHERE-Anweisung. AFAIK versucht monatelang, dies herauszufinden, weil Sie keine Anzahl übereinstimmender Datensätze erhalten können. dynamoDB durchsucht jeden Datensatz in der Tabelle oder im Index und gibt 1000 Datensätze gleichzeitig zurück, die dem Filter entsprechen. Sie haben möglicherweise nur 20 übereinstimmende Datensätze und würden 20 als Zählung erhalten. Es können jedoch 40 in den nächsten 1000 Datensätzen sein und so weiter.
Chris Love
20

Kann auch von der Benutzeroberfläche aus gesehen werden. Gehen Sie zur Registerkarte Übersicht in der Tabelle, Sie sehen die Anzahl der Artikel. Hoffe es hilft jemandem.

coder007
quelle
6
Ja, aber dies hat Einschränkungen: "Speichergröße und Artikelanzahl werden nicht in Echtzeit aktualisiert. Sie werden regelmäßig aktualisiert, ungefähr alle sechs Stunden."
Matthias
Wenn wir die Anzahl einer Abfrage anzeigen möchten, kann dies nicht auf der Registerkarte Übersicht erfolgen. Es werden nur die Gesamtzahl der Zeilen in der Tabelle angezeigt, nicht die Anzahl der Ergebnismengen meiner Abfrage.
Jyotsana Nandwani
6

Wenn Sie zufällig hierher gelangen und mit C # arbeiten, finden Sie hier den Code:

var cancellationToken = new CancellationToken();

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

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

totalCount = result.Count;
ymerej
quelle
Dies funktioniert nicht, wenn Sie mehr als 1 MB Elemente haben.
JohnOpincar
6

Ersetzen Sie den Tabellennamen und verwenden Sie die folgende Abfrage, um die Daten in Ihrer lokalen Umgebung abzurufen:

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

Ersetzen Sie den Tabellennamen und entfernen Sie die Endpunkt-URL, um die Daten in der Produktionsumgebung abzurufen

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"
Ravi Ranjan
quelle
1

Ähnlich wie bei Java in PHP nur Select PARAMETER mit dem Wert 'COUNT' setzen.

$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'
));

und greift einfach so zu:

echo $ result ['Count'];

aber wie Saumitra oben erwähnt seien Sie vorsichtig mit Result largers als 1 MB, in diesem Fall der Verwendung LastEvaluatedKey bis es null zurückgibt die letzte aktualisierte Zählwert zu erhalten.

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

gibt Ihnen die Anzahl der gefilterten Zeilen

wo,

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

Ich poste diese Antwort für alle, die C # verwenden und eine voll funktionsfähige, gut getestete Antwort wünschen, die die Verwendung von Abfragen anstelle von Scans demonstriert. Diese Antwort behandelt insbesondere mehr als 1 MB Größe der zu zählenden Elemente.

        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;
    }
}
JohnOpincar
quelle
-1

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

Ich habe Scan verwendet, um die Gesamtzahl des erforderlichen Tabellennamens zu ermitteln. Das Folgende ist ein Java-Code-Snippet für denselben

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
quelle
-5

Dies ist eine Lösung für AWS JavaScript SDK-Benutzer, die für andere Sprachen fast identisch ist.

Result.data.Count gibt Ihnen, wonach Sie suchen

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

    .then(function(result){

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

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

});
Mustafa Kahraman
quelle
2
Bitte fügen Sie Ihrer Antwort eine Erklärung bei.
WonderWorker