如何修复Lambda从DynamoDB获取指定列的参数验证错误?
问题分析:Lambda函数从DynamoDB获取指定字段失败
问题描述
我希望通过Lambda函数从DynamoDB中仅获取timestamp、address、distance和proximity字段,通过API Gateway返回响应给React Native应用展示,但当前代码运行报错,请问代码存在什么问题?
原代码
import boto3 import json from boto3.dynamodb.conditions import Key, Attr def lambda_handler(event, context): IRAPID_BEACON = 'irapid_beacon' DDB_RESOURCE = boto3.resource('dynamodb') IRAPID_BEACON_DDB_TABLE = DDB_RESOURCE.Table(IRAPID_BEACON) result = IRAPID_BEACON_DDB_TABLE.get_item(Key={'timestamp'}, ProjectionExpression='#timestamp, address, distance, proximity', ExpressionAttributeNames={'#address': 'address'}) return { 'body': result }
错误响应(已翻译)
{ "errorMessage": "参数验证失败:\nKey参数类型无效,值: {'timestamp'}, 类型: <class 'set'>, 合法类型: <class 'dict'>", "errorType": "参数验证错误", "requestId": "3af15dff-d323-49bf-9429-bfce2d26e579", "stackTrace": [ " 文件 \"/var/task/lambda_function.py\", 第14行, 在lambda_handler函数中\n result = IRAPID_BEACON_DDB_TABLE.get_item(Key={'timestamp'}, ProjectionExpression='#timestamp, address, distance, proximity', ExpressionAttributeNames={'#address': 'address'})\n", " 文件 \"/var/runtime/boto3/resources/factory.py\", 第520行, 在do_action函数中\n response = action(self, *args, **kwargs)\n", " 文件 \"/var/runtime/boto3/resources/action.py\", 第83行, 在__call__函数中\n response = getattr(parent.meta.client, operation_name)(*args, **params)\n", " 文件 \"/var/runtime/botocore/client.py\", 第391行, 在_api_call函数中\n return self._make_api_call(operation_name, kwargs)\n", " 文件 \"/var/runtime/botocore/client.py\", 第691行, 在_make_api_call函数中\n request_dict = self._convert_to_request_dict(\n", " 文件 \"/var/runtime/botocore/client.py\", 第739行, 在_convert_to_request_dict函数中\n request_dict = self._serializer.serialize_to_request(\n", " 文件 \"/var/runtime/botocore/validate.py\", 第360行, 在serialize_to_request函数中\n raise ParamValidationError(report=report.generate_report())\n" ] }
代码问题分析
- Key参数格式错误:
get_item要求传入完整的主键键值对字典,你写的{'timestamp'}是集合类型,完全不符合要求。如果timestamp是表的主键,需要传入{'timestamp': '具体时间值'};如果是复合主键,还要加上排序键的键值对(比如{'timestamp': 'xxx', 'id': 'yyy'})。 - ProjectionExpression别名逻辑颠倒:你给
timestamp用了#timestamp别名,但没在ExpressionAttributeNames里定义;反而给不需要别名的address定义了别名,逻辑完全错误。timestamp不是DynamoDB保留字,其实不需要别名,若一定要用别名,需在字典中添加{'#timestamp': 'timestamp'}。 - 返回格式不符合API Gateway要求:API Gateway要求Lambda返回的
body是JSON字符串,直接返回result字典会导致序列化失败,必须用json.dumps()转换。 - API选择潜在错误:如果你的需求是获取多条记录,
get_item只适合获取单条主键匹配的记录,应该改用scan或query方法。
修正后的代码
情况1:获取单条已知主键的记录
import boto3 import json def lambda_handler(event, context): IRAPID_BEACON = 'irapid_beacon' DDB_RESOURCE = boto3.resource('dynamodb') table = DDB_RESOURCE.Table(IRAPID_BEACON) # 替换成实际要查询的timestamp值 target_timestamp = "2024-05-20T12:00:00" try: # 正确传入主键键值对,按需指定返回字段 response = table.get_item( Key={'timestamp': target_timestamp}, ProjectionExpression='timestamp, address, distance, proximity' ) # 提取Item,处理记录不存在的情况 item = response.get('Item', {}) return { 'statusCode': 200, 'body': json.dumps(item) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}) }
情况2:获取多条记录(比如所有符合条件的)
import boto3 import json def lambda_handler(event, context): IRAPID_BEACON = 'irapid_beacon' DDB_RESOURCE = boto3.resource('dynamodb') table = DDB_RESOURCE.Table(IRAPID_BEACON) try: # 用scan获取所有记录,指定返回字段 response = table.scan( ProjectionExpression='timestamp, address, distance, proximity' ) items = response.get('Items', []) # 处理分页(数据量大时需循环获取剩余数据) while 'LastEvaluatedKey' in response: response = table.scan( ProjectionExpression='timestamp, address, distance, proximity', ExclusiveStartKey=response['LastEvaluatedKey'] ) items.extend(response['Items']) return { 'statusCode': 200, 'body': json.dumps(items) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}) }
内容的提问来源于stack exchange,提问作者matchaLover
相关产品推荐
相关产品推荐

