You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Datetime过滤表达式查询DynamoDB报操作数类型错误

DynamoDB查询5分钟前条目报错排查与解决

我尝试查询DynamoDB中早于5分钟的条目,数据存储格式如下:

{
  "main_event_code": {
    "S": "1160"
  },
  "event_code": {
    "S": "9999"
  },
  "last_upload": {
    "S": "2024-05-10T04:09:29.614535Z"
  }
}

我的Python脚本代码如下:

current_utc_time = datetime.now(timezone.utc)
past_time = current_utc_time - timedelta(minutes=5)

# Format both times as ISO 8601 strings
current_utc_time_iso = current_utc_time.strftime('%Y-%m-%dT%H:%M:%SZ')
past_time_iso = past_time.strftime('%Y-%m-%dT%H:%M:%SZ')

# Print the current UTC time and the time minus 5 minutes
print(f"Current UTC Time: {current_utc_time_iso}")
print(f"Time 5 Minutes Ago: {past_time_iso}")

try:
    # Scan the table with a filter for items older than 'past_time'
    response = table.scan(
        FilterExpression="last_upload < :past_time",
        ExpressionAttributeValues={":past_time": {"S": past_time_iso}}
    )

运行脚本后出现以下错误:

Error querying DynamoDB table: An error occurred (ValidationException) when calling the Scan operation: Invalid FilterExpression: Incorrect operand type for operator or function; operator or function: <, operand type: M

但我用AWS CLI执行相同逻辑的命令可以正常返回结果:

aws dynamodb scan --table-name ingestion_queue --filter-expression "last_upload < :val" --expression-attribute-values '{":val":{"S":"2024-05-10T04:23:08Z"}}'

报错原因

错误信息里的operand type: M表示过滤时last_upload被识别为Map类型(M),但实际数据中它是字符串类型(S)。这是因为你使用的boto3资源客户端(boto3.resource('dynamodb'))会自动将DynamoDB原生格式(如{"S": "..."})转换为Python原生类型,但你在ExpressionAttributeValues里又手动指定了DynamoDB原生格式,导致类型不匹配。

AWS CLI直接使用原生DynamoDB格式,所以不会出现这个问题。

解决方法

方法一:使用Python原生类型(推荐)

如果table是通过boto3资源创建的,直接传入Python字符串即可,SDK会自动处理类型转换:

response = table.scan(
    FilterExpression="last_upload < :past_time",
    ExpressionAttributeValues={":past_time": past_time_iso}
)

方法二:使用条件表达式构建器

通过boto3.dynamodb.conditions.Attr构建过滤表达式,避免类型歧义:

from boto3.dynamodb.conditions import Attr

response = table.scan(
    FilterExpression=Attr('last_upload').lt(past_time_iso)
)

方法三:切换到boto3低级客户端

如果坚持使用DynamoDB原生格式,可改用boto3.client('dynamodb'),此时所有参数都需要用原生格式:

import boto3

client = boto3.client('dynamodb')
response = client.scan(
    TableName='ingestion_queue',
    FilterExpression="last_upload < :past_time",
    ExpressionAttributeValues={":past_time": {"S": past_time_iso}}
)

内容的提问来源于stack exchange,提问作者Matt Winer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 04:18:18