咨询DynamoDB对两种日期格式排序键的Between查询行为
背景信息
现有DynamoDB表结构及数据如下:
| orderId | order_date | created_at | details |
|---|---|---|---|
| 123 | 2023-05-10 10:04:05 | Date#2023-05-10T00:00:00 | {} |
| 32132 | 2023-05-11 11:04:05 | Date#2023-05-11T00:00:00 | {} |
注:orderId为分区键,order_date和created_at均为排序键;其中order_date格式为YYYY-MM-DD HH:MM:SS(非ISO标准格式),created_at为Date#前缀+ISO格式日期的复合字符串。
关键前提:DynamoDB对排序键的Between查询仅基于字符串的UTF-8字典序进行比较,不会解析字符串的日期语义——官方文档提到的“支持ISO格式日期查询”,本质是因为ISO格式日期的字符串字典序与实际日期时序完全匹配,能得到符合预期的结果,而非DynamoDB具备日期识别能力。
1. 对order_date执行Between查询的表现
order_date的格式YYYY-MM-DD HH:MM:SS虽然不是ISO标准,但字符串的字符顺序与日期的时序逻辑完全一致:年、月、日、时、分、秒从左到右依次按数字大小排列,因此字典序比较的结果和日期范围的预期完全吻合。
比如执行order_date BETWEEN '2023-05-10 00:00:00' AND '2023-05-10 23:59:59',会正确返回orderId=123的记录;查询2023-05-10 00:00:00到2023-05-11 23:59:59则会返回两条记录。
但要注意:这种匹配是格式巧合导致的,如果order_date的格式改成非左对齐的日期格式(比如MM/DD/YYYY),字典序就会和日期时序脱节,查询结果就会不符合预期。
2. 对created_at执行Between查询的表现
created_at的格式是Date#前缀+ISO标准日期字符串,由于前缀固定,后面的ISO日期部分的字典序依然和日期时序一致,因此只要查询参数也遵循相同的格式(Date#+ISO日期),Between查询的结果会符合预期的日期范围。
比如执行created_at BETWEEN 'Date#2023-05-10T00:00:00' AND 'Date#2023-05-10T23:59:59',会返回orderId=123的记录;如果查询范围包含Date#2023-05-11T00:00:00,则会同时返回两条记录。
需要注意的点:
- 如果查询参数遗漏了
Date#前缀(比如直接用2023-05-10T00:00:00),由于字符串字典序中纯日期字符串会排在Date#开头的字符串之前,查询会返回空结果。 - 如果
created_at的日期部分格式错误(比如数据中的Date#2023-05-101T00:00:00,这里的101是非法日期),字典序比较会按字符串字面量处理,导致结果不符合实际日期逻辑。
内容的提问来源于stack exchange,提问作者Shailendra

