DynamoDB Filter-Expression无返回结果问题排查求助
问题排查:DynamoDB按username筛选无返回结果
我有一个DynamoDB表,其中包含一条数据。通过API Gateway调用处理数据库请求的Lambda函数,执行curl {api link}/items/test时,Lambda函数应按指定username筛选,但未返回任何结果,其他接口调用均正常。
以下是处理该请求的Lambda代码:
switch (event.routeKey) { case "GET /items/{username}": body = await dynamo.send( new ScanCommand({ TableName: tableName, ExpressionAttributeValues: {":u": { S: event.pathParameters.username }}, FilterExpression: "username = :u", ProjectionExpression: "username", }) ); body = body.Item; break; case "GET /items/{username}/{exercise_name}": body = await dynamo.send( new GetCommand({ TableName: tableName, Key: { username: event.pathParameters.username, exercise_name: event.pathParameters.exercise_name }, }) ); body = body.Item; break; case "PUT /items": let requestJSON = JSON.parse(event.body); await dynamo.send( new PutCommand({ TableName: tableName, Item: { username: requestJSON.username, exercise_name: requestJSON.exercise_name, records: requestJSON.records, }, }) ); body = `Put/Updated item ${requestJSON.exercise_name} for user ${requestJSON.username} `; break; default: throw new Error(`Unsupported route: "${event.routeKey}"`); }
我尝试了多种筛选表达式变体,但均未得到结果,变体如下:
ExpressionAttributeValues: {":u": event.pathParameters.username }, FilterExpression: "contains(username, :u )"
ExpressionAttributeValues: {":u": { "S": event.pathParameters.username }}, FilterExpression: "username = :u",
问题根源与修正方案
数据格式不匹配
PUT命令使用原生JavaScript字符串(username: requestJSON.username)存储数据,但Scan命令里手动添加了低级API的类型标识{ S: ... }。AWS SDK v3的命令(如ScanCommand、PutCommand)默认支持原生类型,无需手动指定类型包装,这会导致筛选条件与实际存储的数据格式不匹配,无法命中。Scan结果取值错误
ScanCommand的返回结果中,符合条件的数据存放在Items数组里,而非Item字段(Item是GetCommand的返回字段)。当前的body = body.Item会直接得到undefined。低效的Scan使用
从GetCommand的代码可知,username是复合主键的一部分,此时应该用QueryCommand替代ScanCommand,基于主键查询效率更高,且不需要FilterExpression。
修正后的代码(推荐用Query):
case "GET /items/{username}": body = await dynamo.send( new QueryCommand({ TableName: tableName, KeyConditionExpression: "username = :u", ExpressionAttributeValues: {":u": event.pathParameters.username}, ProjectionExpression: "username" }) ); body = body.Items; // Query返回的是符合条件的结果数组 break;
若坚持使用Scan的修正方案:
case "GET /items/{username}": body = await dynamo.send( new ScanCommand({ TableName: tableName, ExpressionAttributeValues: {":u": event.pathParameters.username}, // 去掉类型包装 FilterExpression: "username = :u", ProjectionExpression: "username" }) ); body = body.Items; // 取Items数组 break;
内容的提问来源于stack exchange,提问作者Giorgio Matessi
相关产品推荐
相关产品推荐

