【问题标题】:Boto3 and DynamoDB - How to mimic AggregationBoto3 和 DynamoDB - 如何模拟聚合
【发布时间】:2021-03-15 20:16:43
【问题描述】:

我在 DynamoDB 中有一个表格,格式如下:

DeviceId (PK) SensorDataType SensorValue CurrentTime (SK)
BSMD002 HeartRate 86 2021-03-13 14:50:17.292663
BSMD002 HeartRate 106 2021-03-13 14:50:17.564644
BSMD002 HeartRate 97 2021-03-13 14:50:17.854391

我正在使用 boto3 从该表中提取数据,并希望创建一个基于用户输入的新表(DeviceId、日期范围)。该表将包含传感器类型数据 - 按分钟分组的最大值、最小值和平均值。

我知道 DynamoDB 不支持聚合,使用 Streams + Lambda 是更有效的方法。但是想了解在boto3中是否有办法做到这一点。到目前为止,已经按照以下代码提取数据。

import boto3
import time
from datetime import datetime, timedelta
from boto3.dynamodb.conditions import Key, Attr

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('BSMDataTable')

devicetag = input(" Enter the Device ID to find: ").upper()
datefrom = input("Enter Starting Date in YYYY-MM-DD format: ")
dateto = input("Enter Ending Date in YYYY-MM-DD format: ")

fe = Key('CurrentTime').between(datefrom,dateto) & Key('DeviceId').eq(devicetag);
response = table.query(
                KeyConditionExpression=fe
            )
for i in response['Items']:
    print(i)

【问题讨论】:

  • 请将一些示例数据放入我在帖子中编辑的表格中,并告诉我们您到底在努力解决什么问题,这看起来是一个有希望的开始。同样在代码中,TimeStamp 列似乎被命名为 CurrentTime?
  • 是的,CurrentTime 是时间戳。
  • DeviceId CurrentTime SensorType Reading A001 3/13/2021 11:01 Temp 82 A002 3/13/2021 11:01 Heart 92
  • 请编辑您的问题,时间格式有问题,您将无法真正对它们进行范围查询 - 将其存储为 ISO8601 格式或 Unix Epoch。

标签: amazon-web-services amazon-dynamodb boto3 dynamodb-queries


【解决方案1】:

其实你们很亲近。缺少的只是响应中项目的聚合。

这是一个例子。 我们首先按分钟对项目进行分组,然后计算每分钟的统计数据。

import statistics
import itertools

# Sample data
response = {
    "Items": [
        {"DeviceId": "BSMD002", "SensorDataType": "HeartRate", "SensorValue": 86, "CurrentTime": "2021-03-13 14:50:17.123"},
        {"DeviceId": "BSMD002", "SensorDataType": "HeartRate", "SensorValue": 100, "CurrentTime": "2021-03-13 14:50:18.123"},
        {"DeviceId": "BSMD002", "SensorDataType": "HeartRate", "SensorValue": 19, "CurrentTime": "2021-03-13 14:51:17.123"},
    ]
}

# Group the response by items per minute
items_by_minute = itertools.groupby(
    response["Items"], 
    key=lambda x: x["CurrentTime"][:16]  #  The first 16 characters including the minute
)

# Calculate the statistics for each minute
for minute, items in items_by_minute:
    values_per_minute = [item["SensorValue"] for item in items]
    
    avg = statistics.mean(values_per_minute)
    min_value = min(values_per_minute)
    max_value = max(values_per_minute)
    
    print(f"Minute: {minute} / Average {avg} / Min {min_value} / Max {max_value}")

输出

Minute: 2021-03-13 14:50 / Average 93 / Min 86 / Max 100
Minute: 2021-03-13 14:51 / Average 19 / Min 19 / Max 19

【讨论】:

  • 对此的附加查询。如果我想做一个嵌套的 Groupby ...首先在 SensorDataType 上,然后在 Minute agg 上,如何实现..
  • 将 lambda 表达式更改为 lambda x: f"{x['SensorDataType']}_{x["CurrentTime"][:16]}"
  • 我犯了一些基本错误..SensorType 分组然后最小聚合不起作用..items_by_minute = sorted(col, key=lambda x: (x["SensorDataType"],x["CurrentTime"][:16]) ) items_by_minute = itertools.groupby(col, key=lambda x: (x["SensorDataType"],x["CurrentTime"][:16]))
  • 您能否为此创建第二个问题?添加更多子问题会使这对未来的读者不太有用。请包括一个最低限度的可验证示例,例如我的回答中的代码以及您的补充和清晰的解释什么有效,什么无效。如果到目前为止我的回答解决了您的问题,请随时接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
  • 1970-01-01
  • 2017-10-24
相关资源
最近更新 更多