从DynamoDB过滤传感数据的两个问题:Partition-Key排序与时间值筛选
问题解答
1. Partition Key的time字段排序问题
DynamoDB返回的Item本质为字典类型,Python 3.7之前的原生字典不保留插入顺序,且DynamoDB服务端本身也不会保证返回字段的先后顺序,因此time字段不会默认出现在首位,该现象不影响数据正确性,仅需在输出时手动控制顺序即可:
for item in items: # 先输出time字段,再输出其余字段,保证time固定在首位 format_item = {"time": item["time"]} format_item.update({k:v for k,v in item.items() if k != "time"}) print(format_item)
如需更稳定的有序结构,可引入collections.OrderedDict实现。
2. 按指定时间过滤条目
你当前使用的scan是全表扫描操作,仅适合小表测试使用,数据量较大时会产生极高的读开销且性能极差。如果time是你的表分区键(Partition Key),优先使用query操作,效率更高。
实现方案
首先确认你的time字段存储格式,两种常见格式的过滤方法如下:
场景1:time为ISO时间字符串(如2021-08-23T16:xx:xx)
小表临时过滤(基于scan,不推荐生产使用)
import boto3 from boto3.dynamodb.conditions import Attr dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('ProjektarbeitTable') # 过滤所有time字段以2021-08-23T16开头的条目 response = table.scan( FilterExpression=Attr('time').begins_with('2021-08-23T16') ) items = response['Items']
生产环境推荐(基于query,要求time为分区键)
import boto3 from boto3.dynamodb.conditions import Key dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('ProjektarbeitTable') response = table.query( KeyConditionExpression=Key('time').begins_with('2021-08-23T16'), ScanIndexForward=True # 按时间正序返回,改为False则为倒序 ) items = response['Items']
场景2:time为Unix时间戳
先计算目标小时的起止时间戳(2021年8月23日16点UTC时间对应起止戳为1629734400、1629737999),再用范围条件过滤:
# 以query为例,scan逻辑同理替换条件即可 response = table.query( KeyConditionExpression=Key('time').between(1629734400, 1629737999) )
关于返回数据顺序异常的说明
DynamoDB的scan操作返回结果是按分区键的哈希值排序,并非按时间自然排序。如需固定顺序,优先用query操作配合ScanIndexForward参数控制排序规则,也可在本地拿到数据后手动排序:
# 本地按time字段升序排序 items_sorted = sorted(items, key=lambda x: x['time'])
内容的提问来源于stack exchange,提问作者ElPhilippo
相关产品推荐
相关产品推荐

