如何从DynamoDB获取项目数?

sam*_*lee 53 database amazon-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']);
Run Code Online (Sandbox Code Playgroud)

此代码使所有用户数据高于我的观点.

如果$ result的计数是100,000,$ result太大了.它会超出查询大小的限制.

我需要帮助.

Dan*_*eim 110

使用aws dynamodb cli,您可以通过扫描获得它,如下所示:

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"
Run Code Online (Sandbox Code Playgroud)

响应将类似于:

{
    "Count": 123,
    "ScannedCount": 123,
    "ConsumedCapacity": null
}
Run Code Online (Sandbox Code Playgroud)

注意这个信息是实时的,与describe-table api 形成对比

  • 这个答案不正确,至少在问题的上下文中是不正确的。问题是如何获取与过滤表达式匹配的记录的计数,从而与 WHERE 语句进行比较。据我所知,几个月来你一直试图解决这个问题,但你无法获得匹配记录的计数。dynamoDB 将遍历表或索引中的每条记录并返回与过滤器匹配的记录,一次 1000 条记录。您可能只有 20 条匹配记录,并且会得到 20 作为计数。然而,接下来的 1000 条记录中可能有 40 条,依此类推。 (7认同)
  • @JHH 我刚刚试过这个,它似乎确实使用了读取容量单位。根据 DynamoDB 控制台,我的查询消耗了大约 12 个单位(仅配置了 1 个);我假设它正在利用突发容量来为查询提供服务。 (2认同)
  • @Zodman 感谢您的尝试!我再次通读了文档,实际上我发现了一个关于我之前错过的计数的声明:“获取项目的计数使用相同数量的读取容量单位,并受相同的项目大小计算,因为 DynamoDB 必须读取每个项目以增加计数。” https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/CapacityUnitCalculations.html#ItemSizeCalculations.Reads (2认同)
  • 有人可能认为缓存计数,至少在最终一致的边界内,使其仅消耗一个 CU 是可行的,但也许只获取计数并不是一种非常常见的情况。 (2认同)
  • @HelenNeely是的,这种方式提供了最新的项目数. (2认同)

bob*_*bob 24

我来得太晚了,但想扩展丹尼尔关于使用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"
Run Code Online (Sandbox Code Playgroud)

会给

{
    "Count": 2945,
    "ScannedCount": 7874,
    "ConsumedCapacity": null
}
Run Code Online (Sandbox Code Playgroud)

即,ScannedCount是总计数,Count是按给定表达式 (fieldName=123) 过滤的项目数。


mko*_*bit 17

您可以使用Select参数并COUNT在请求中使用.它"返回匹配项的数量,而不是匹配项本身".重要的是,由Saumitra R. Bhave在评论中提出,"如果查询结果集的大小大于1 MB,则ScannedCount和Count将仅表示总项目的部分计数.您将需要执行多个查询操作以检索所有结果".

我不熟悉PHP,但是你可以在Java上使用它.然后Count,'Items'您可以使用Count响应中 - 而不是使用(我猜测它是PHP中的函数)- $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();
Run Code Online (Sandbox Code Playgroud)

如果您不需要模拟该WHERE子句,则可以使用DescribeTable请求并使用结果项目计数来获得估计值.

指定表中的项目数.DynamoDB大约每六个小时更新一次该值.最近的更改可能不会反映在此值中.

  • 我认为这里有一个小问题,根据http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.Count说"如果查询结果集的大小更大超过1 MB,则ScannedCount和Count将仅表示总项目的部分计数",这基本上意味着首先获取项目然后计数,如果获取项目的大小超过1MB,则"计数"将被分页 (15认同)
  • 只是为了完成您的回答,正如所指出的,您可能需要重复调​​用,直到 LastEvaluatedKey 不再出现在结果中,这可能看起来像这样(到上面代码的结尾):`while(result.getLastEvaluatedKey() !=null){ request.setExclusiveStartKey(result.getLastEvaluatedKey()); 结果 = dynamoDBClient.query(request); count+= result.getCount(); }` (2认同)

Joh*_*car 10

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

Run Code Online (Sandbox Code Playgroud)


小智 9

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

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

小智 9

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

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT" --endpoint-url http://localhost:8000
Run Code Online (Sandbox Code Playgroud)

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

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"
Run Code Online (Sandbox Code Playgroud)


Epi*_*edy 7

如果有人正在寻找直接的 NodeJS Lambda 计数解决方案:

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

// data.Count -> number of elements in table.
Run Code Online (Sandbox Code Playgroud)


lee*_*gan 7

为这个问题添加一些额外的上下文。Scan在某些情况下,表获取活动项目计数是有意义的。但是,如果这种情况经常发生或者您有大型表,那么从成本和性能的角度来看,这可能会很昂贵。下面,我重点介绍了获取表格项目数的 3 种方法。

1.Scan

使用 aScan要求您读取表中的每一项,这对于一次性查询非常有效,但它不可扩展并且可能变得相当昂贵。使用Select: COUNT将阻止返回数据,但您仍然必须为读取整个表付费。

优点

  • 获取最新的项目计数(“实时”)
  • 是一个简单的API调用
  • 可以并行运行以减少时间

缺点

  • 读取整个数据集
  • 性能缓慢
  • 成本高

CLI 示例

aws dynamodb scan \
--table-name test \
--select COUNT
Run Code Online (Sandbox Code Playgroud)

2.DescribeTable

DynamoDB DescribeTableAPI 为您提供 ItemCount 的估计值,该值大约更新。每 6 小时一次。

指定表中的项目数。DynamoDB 大约每六个小时更新一次该值。最近的更改可能不会反映在此值中。参考号

调用此 API 可以为您提供即时响应,但是,ItemCount 的值可能会过时长达 6 小时。在某些情况下,该值可能就足够了。

优点

  • 即时响应
  • 检索 ItemCount 无需任何成本
  • 可以经常调用

缺点

  • 数据最多可能会过时 6 小时。

CLI 示例

aws dynamodb describe-table \
--table-name test \
--query Table.ItemCount
Run Code Online (Sandbox Code Playgroud)

描述表和 CloudWatch

如前所述DescribeTable,更新您的表 ItemCount 大约。每 6 小时一次。我们可以获取该值并将其绘制在自定义 CloudWatch 图表上,该图表允许您随时间监控表 ItemCount,从而为您提供历史数据。

优点

  • 提供历史数据
  • 推断您的 ItemCount 如何随时间变化
  • 相当容易实施

缺点

  • 数据最多可能会过时 6 小时。

执行

使用 CloudWatch 跟踪 DynamoDB 存储历史记录展示了如何DescribeTable使用 EventBridge 和 Lambda 定期自动将 的值推送到 CloudWatch,但是,它旨在推送TableSizeBytes而不是ItemCount. 对 Lambda 进行一些小的修改将允许您记录ItemCount.


yme*_*rej 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;
Run Code Online (Sandbox Code Playgroud)

  • 否决,因为它不适用于超过 1MB 的项目,并且除非您喜欢锁定 UI 线程,否则不应使用 Task.Result。 (2认同)