DynamoDB Count Group By


DynamoDB Count Group By

我们正在尝试搜索dynamodb,并需要获得组内对象的计数,如何做到这一点?

我已经尝试过了,但是当添加第二个数字时,这不起作用:

$search = array(
    'TableName'     => 'dev_adsite_rating',
    'Select'        => 'COUNT',
    'KeyConditions' => array(
        'ad_id' => array(
            'ComparisonOperator' => 'EQ',
            'AttributeValueList' => array(
                array('N' => 1039722, 'N' => 1480)
            )
        )
    )
);
$response = $client->query($search);

sql版本看起来像这样:

select ad_id, count(*) 
from dev_adsite_rating
where ad_id in(1039722, 1480)
group by ad_id;

那么,我们有办法做到这一点吗?

尝试在DynamoDB上执行这样的查询比在SQL世界中稍微复杂一些。要执行这样的操作,需要考虑以下几点

  1. EQ ONLY Hash Key:要执行这种查询,您需要进行两个查询(即ad_id EQ 1039722/ad_id EQ 1480)
  2. 通过查询分页:由于dynamodb以增量方式返回结果集,因此需要对结果分页。点击这里了解更多。
  3. 运行"Count":您可以从响应中获取"Count"属性,并在对两个查询的结果进行分页时将其添加到运行总数中。查询API

您可以添加一个由DynamoDBStream触发的Lambda函数,以便动态地聚合您的数据,在您的示例中,将相关计数器添加+1。然后,您的搜索函数将直接检索聚合的数据。

示例:如果您有一个每周在线投票系统,您需要存储每个投票(也要检查没有用户投票两次),您可以使用以下命令实时汇总投票:

export const handler: DynamoDBStreamHandler = async (event: DynamoDBStreamEvent) => {
  await Promise.all(event.Records.map(async record => {
    if (record.dynamodb?.NewImage?.vote?.S && record.dynamodb?.NewImage?.week?.S) {
      await addVoteToResults(record.dynamodb.NewImage.vote.S, record.dynamodb.NewImage.week.S)
    }
  }))
}

其中addVoteToResults类似于:

export const addVoteToResults = async (vote: string, week: string) => {
  await dynamoDbClient.update({
      TableName: 'table_name',
      Key: { week: week },
      UpdateExpression: 'add #vote :inc',
      ExpressionAttributeNames: {
        '#vote': vote
      },
      ExpressionAttributeValues: {
        ':inc': 1
      }
    }).promise();
}

之后,当投票结束时,您可以使用单个get语句检索每周的总票数。此解决方案还有助于分散写/读负载,而不是在执行搜索功能时大幅增加负载。