如何从DynamoDB获取项目计数?


79

我想了解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太大。并且它将超出查询大小的限制。

我需要帮助。

Answers:


28

您可以使用Select参数并COUNT在请求中使用。它“返回匹配项的数量,而不是匹配项本身”。重要的,因为从小在评论由Saumitra R.巴维“如果查询结果集的大小大于1 MB,然后ScannedCount和伯爵将只占总项目的部分数量。您将需要执行多个查询操作以便检索所有结果”

我对PHP不熟悉,但是这里是如何在Java中使用它。然后,而不是使用Count(我猜是在PHP函数)上'Items',你可以使用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,ScannedCount并且Count仅代表全部项目的一部分。您需要执行多项Query操作来检索所有结果(请参阅对表查询结果进行分页)。


16
我认为docs.aws.amazon.com/amazondynamodb/latest/developerguide/…还是有一个小问题,它说:“如果查询结果集的大小大于1 MB,则ScannedCount和Count将代表“仅对全部项目进行部分计数”,这基本上意味着先提取项目然后进行计数,如果所提取项目的大小超过1MB,甚至“计数”也会被分页
Saumitra R. Bhave

我不想窃取@mkobit的原始作品,但这是一种使用流畅链接的方法:AmazonDynamoDBClientBuilder.standard().withRegion(region).withCredentials(credentialsProvider).build() .query(new QueryRequest(freeKeysTableName).withSelect(Select.COUNT)).getCount()
Sridhar Sarnobat,

1
只是为了完成您的回答,正如您指出的那样,您可能必须重复呼叫直到结果中不再存在LastEvaluatedKey为止,并且可能看起来像这样(到上面的代码末尾): while(result.getLastEvaluatedKey()!=null){ request.setExclusiveStartKey(result.getLastEvaluatedKey()); result = dynamoDBClient.query(request); count+= result.getCount(); }
Peter Koncz

136

使用aws dynamodb cli,您可以通过以下方式进行扫描

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

响应将类似于以下内容:

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

请注意,与describe-table api相反,此信息是实时的


2
@JHH我刚刚尝试过,它似乎确实使用了读取容量单位。根据DynamoDB控制台,我的查询消耗了大约12个单位(仅配置了1个);我假设它正在利用突发容量来服务查询。
Zodman

2
@Zodman感谢您尝试!我再次通读了文档,实际上发现了一条有关我以前错过的计数的声明:“获取项目计数使用相同数量的读取容量单位,并且要进行相同的项目尺寸计算,因为DynamoDB必须读取每个项以增加计数。” docs.aws.amazon.com/amazondynamodb/latest/developerguide/…–
JHH

2
可能有人认为,至少在最终一致的边界内缓存计数,使之仅消耗一个CU是可行的,但也许只获取计数并不是很常见的情况。
JHH

2
@HelenNeely是的,这种方式提供了最新的物品计数。
丹尼尔·布本海姆'18

1
至少在问题上下文中,这个答案是不正确的。问题是如何获取与过滤器表达式匹配的记录数,从而与WHERE语句进行比较。AFAIK经过数月的努力才发现您无法获得匹配记录的数量。dynamoDB将遍历表或索引中的每个记录,并返回与过滤器匹配的记录,一次返回1000条记录。您可能只有20条匹配记录,并且将获得20条计数。但是,接下来的1000条记录中可能有40条,依此类推。
克里斯·爱

20

也可以从UI中看到。转到表格上的概览标签,您将看到项目数。希望它能帮助某人。


6
是的,但这有其局限性:“存储大小和项目数不会实时更新。它们会定期(大约每六个小时)更新一次。”
matthias

另外,如果我们想查看查询的计数,则无法在“概述”选项卡中完成。它仅显示表中的总行,而不是查询的结果集数。
Jyotsana Nandwani

6

如果您碰巧到达此处,并且正在使用C#,则代码如下:

var cancellationToken = new CancellationToken();

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

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

totalCount = result.Count;

如果您的项目超过1MB,则无法使用。
JohnOpincar

6

替换表名,并使用以下查询获取本地环境中的数据:

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

替换表名并删除端点url以获取生产环境中的数据

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

1

与PHP中的Java类似,仅设置值为'COUNT'的Select PARAMETER

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

并像这样访问它:

echo $ result ['Count'];

但正如上述Saumitra所提请注意,对于大于1 MB的结果集,在这种情况下,请使用LastEvaluatedKey til,直到返回最后一个更新的计数值,它会返回null。



0
len(response['Items'])

将为您提供过滤后的行数

哪里,

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

0

我将这个答案发布给使用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;
    }
}

-1

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

-2

我使用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);

-5

这是适用于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){

});

2
请在回答中附上说明。
WonderWorker
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.