簡體   English   中英

如何從 DynamoDB 獲取項目計數?

[英]How to get item count from DynamoDB?

我想通過 DynamoDB 查詢了解項目計數。

我可以查詢 DynamoDB,但我只想知道“項目總數”。

例如,MySQL 中的“SELECT COUNT(*) FROM...WHERE...”

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

此代碼獲取的所有用戶數據都高於我的觀點。

如果 $result 的計數為 100,000,則 $result 太大了。 而且它會超過查詢大小的限制。

我需要幫助。

使用aws dynamodb cli,您可以通過掃描獲取它,如下所示:

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

響應將類似於以下內容:

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

請注意,與描述表api 相比,此信息是實時的

您可以使用Select參數並在請求中使用COUNT 它“返回匹配項的數量,而不是匹配項本身”。 重要的是,正如Saumitra R. Bhave 在評論中提出的“如果 Query 結果集的大小大於 1 MB,則 ScannedCount 和 Count 將僅表示總項目的部分計數。您將需要執行多個查詢操作以檢索所有結果”

我不熟悉 PHP,但這里是如何將它與 Java 一起使用。 然后,而不是在'Items'上使用Count (我猜這是 PHP 中的一個函數),您可以使用響應中Count- $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();

如果您不需要模擬WHERE子句,您可以使用DescribeTable請求並使用生成的項目計數來獲得估計值。

指定表中的項目數。 DynamoDB 大約每六小時更新一次該值。 最近的更改可能不會反映在此值中。

此外,如Saumitra R. Bhave在對此答案的評論中所指出的文檔中的重要說明:

如果Query結果集的大小大於 1 MB,則ScannedCountCount僅表示總項目的部分計數。 您需要執行多個Query操作來檢索所有結果(請參閱Paginating Table Query Results )。

也可以從 UI 中看到。 轉到表格上的概覽選項卡,您將看到項目數。 希望它可以幫助某人。

替換表名並使用以下查詢獲取本地環境中的數據:

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

替換表名並刪除端點url以獲取生產環境的數據

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

如果您碰巧到達這里,並且正在使用 C#,則代碼如下:

var cancellationToken = new CancellationToken();

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

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

totalCount = result.Count;

我在這里為時已晚,但想擴展 Daniel 關於使用aws cli包含過濾器表達式的答案。

跑步

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

會給

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

也就是說, ScannedCount是總計數, Count是由給定表達式 (fieldName=123) 過濾的項目數。

類似於 PHP 中的 Java 僅設置 Select PARAMETER 值為 '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'
));

並像這樣訪問它:

回聲 $result['Count'];

但是正如上面提到的Saumitra 對大於 1 MB 的結果集要小心,在這種情況下,使用 LastEvaluatedKey 直到它返回 null 來獲取最后更新的計數值。

在斯卡拉:

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()

我正在為任何使用 C# 的人發布這個答案,他們想要一個功能齊全、經過充分測試的答案,演示使用查詢而不是掃描。 特別是,這個答案處理超過 1MB 大小的要計數的項目。

        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;
    }
}

您可以使用 dynamodb 映射器查詢。

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

它調用loadAllResults() ,它會延遲加載下一個可用結果,直到 allResultsLoaded。

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

我們可以通過創建表描述請求https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html來獲取dynamo DB表的項目計數

len(response['Items'])

會給你過濾的行數

在哪里,

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

如果有人正在尋找直接的 NodeJS Lambda 計數解決方案:

const data = await dynamo.scan({ Select: "COUNT", TableName: "table" }).promise();

// data.Count -> number of elements in table.

DynamoDB 現在在 UI 中有一個“獲取實時項目計數”按鈕。 如果您有一個會消耗讀取容量的大表,請注意生產警告。

實時項目計數

實時項目計數

這就是您使用DynamoDBMapper (Kotlin 語法)的方式,示例完全沒有過濾器:

dynamoDBMapper.count(MyEntity::class.java, DynamoDBScanExpression())

為這個問題添加一些額外的上下文。 在某些情況下, Scan表格以獲得活動項目計數是有意義的。 但是,如果這種情況經常發生,或者如果您有大型表,那么從成本和性能的角度來看,它可能會很昂貴。 下面,我重點介紹了 3 種獲取表格項目數的方法。

1. Scan

使用Scan需要您讀取表中的每一項,這對於一次性查詢非常有效,但它不可擴展並且可能變得非常昂貴。 使用Select: COUNT將阻止返回數據,但您仍然必須為讀取整個表付費。

優點

  • 獲取最新的項目計數(“實時”)
  • 是一個簡單的 API 電話
  • 可以並行運行以減少時間

缺點

  • 讀取整個數據集
  • 性能緩慢
  • 高成本

命令行示例

aws dynamodb scan \
--table-name test \
--select COUNT

2. DescribeTable

DynamoDB DescribeTable API 為您提供了 ItemCount 的估計值,該值大約更新了。 每 6 小時一次。

指定表中的項目數。 DynamoDB 大約每六小時更新一次此值。 最近的更改可能不會反映在此值中。 參考

調用此 API 可為您提供即時響應,但是,ItemCount 的值最多可能已過時 6 小時。 在某些情況下,這個值可能就足夠了。

優點

  • 即時響應
  • 檢索 ItemCount 無需任何費用
  • 可以經常調用

缺點

  • 數據可能會過時長達 6 小時。

CLI 示例

aws dynamodb describe-table \
--table-name test \
--query Table.ItemCount

DescribeTable 和 CloudWatch

如前所述, DescribeTable更新您的表 ItemCount 大約。 每 6 小時一次。 我們可以在自定義 CloudWatch 圖形上獲取該值和 plot,它允許您隨時間監控表 ItemCount,為您提供歷史數據。

優點

  • 提供歷史數據
  • 推斷您的 ItemCount 如何隨時間變化
  • 相當容易實施

缺點

  • 數據可能會過時長達 6 小時。

執行

使用 CloudWatch 跟蹤 DynamoDB 存儲歷史展示了如何使用 EventBridge 和 Lambda 定期將DescribeTable的值自動推送到 CloudWatch,但是,它旨在推送TableSizeBytes而不是ItemCount 對 Lambda 的一些小修改將允許您記錄ItemCount

$aws = new Aws\DynamoDb\DynamoDbClient([
    'region'  => 'us-west-2',
    'version' => 'latest',
]);

$result = $aws->scan(array(
    'TableName' => 'game_table',
    'Count' => true
));

echo $result['Count'];

我使用 scan 來獲取所需 tableName 的總數。以下是相同的 Java 代碼片段

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

這是 AWS JavaScript SDK 用戶的解決方案,其他語言幾乎相同。

Result.data.Count 會給你你想要的

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

    .then(function(result){

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

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

});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM