AWS SDK v2转v3 DynamoDB查询方法出错,请求排查问题
AWS SDK v2迁移到v3后DynamoDB查询报错:TypeError: Cannot read properties of undefined (reading '0')
我有一个可正常运行的AWS SDK v2 DynamoDB记录查询方法,但迁移到v3后方法运行失败,报错信息如下:
C:\Users\xxx\Desktop\_REPOS\_PERSONAL\yyy\backend\node_modules\@aws-sdk\client-dynamodb\dist-cjs\index.js:1004 return visitor._(value.$unknown[0], value.$unknown[1]); ^ TypeError: Cannot read properties of undefined (reading '0')
报错的极简v3示例代码
import { DynamoDBClient, QueryCommand, QueryCommandInput } from "@aws-sdk/client-dynamodb"; import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb"; export const marshallOptions = { convertEmptyValues: false, // false, by default. removeUndefinedValues: true, // false, by default. convertClassInstanceToMap: true, // false, by default. }; export const unmarshallOptions = { wrapNumbers: false, // false, by default. }; (async()=>{ const dynamoDBClient = new DynamoDBClient({ region: "us-east-1" }); const dynamoDocClient = DynamoDBDocumentClient.from(dynamoDBClient, { marshallOptions, unmarshallOptions, } ); let params:QueryCommandInput={ TableName: 'notesV2Table', IndexName: 'topic-index', KeyConditionExpression: '#ty = :val', ExpressionAttributeNames: { '#ty': 'topic' }, ExpressionAttributeValues: { ':val': 'Dynamo' } as any } //return await dynamoDocClient.send(new QueryCommand(params)); return await dynamoDBClient.send(new QueryCommand(params)); })()
运行失败的v3代码
export const marshallOptions = { // Whether to automatically convert empty strings, blobs, and sets to `null`. convertEmptyValues: false, // false, by default. // Whether to remove undefined values while marshalling. removeUndefinedValues: true, // false, by default. // Whether to convert typeof object to map attribute. convertClassInstanceToMap: true, // false, by default. }; export const unmarshallOptions = { // Whether to return numbers as a string instead of converting them to native JavaScript numbers. wrapNumbers: false, // false, by default. }; // Create a DynamoDB client const dynamoDBClient = new DynamoDBClient({ region: "us-east-1" }); // Full document client export const dynamoDocClient = DynamoDBDocumentClient.from(dynamoDBClient, { marshallOptions, unmarshallOptions, }); export var queryNotesByTopic = async function (event: any) { try { console.log(`event`, event); if (event.hasOwnProperty("obj")) event = event.obj; console.log(`queryNotesByTopic object: `, event); //let topic = event.queryStringParameters["topic"] || null; //GET param let topic = event["topic"]; if (!topic) throw `invalid topic ${topic}`; console.log(`query for each row with id: ${topic}`); //this matches any cards with the id 'Dynamo' var params = { TableName: TABLE_NAME, IndexName: "topic-index", KeyConditionExpression: "#ty = :val", ExpressionAttributeNames: { "#ty": "topic", }, ExpressionAttributeValues: { ":val": topic, }, }; console.log(params); return await dynamoDocClient.send(new QueryCommand(params)); } catch (e) { throw e; } };
可正常运行的v2代码
export var queryNotesByTopic = async function (event: any) { const docClient = new AWS.DynamoDB.DocumentClient({ apiVersion: "2012-08-10", }); try { console.log(`event`, event); if (event.hasOwnProperty("obj")) event = event.obj; console.log(`queryNotesByTopic object: `, event); //let topic = event.queryStringParameters["topic"] || null; //GET param let topic = event["topic"]; if (!topic) throw `invalid topic ${topic}`; console.log(`query for each row with id: ${topic}`); //this matches any cards with the id 'Dynamo' var params = { TableName: TABLE_NAME, IndexName: "topic-index", KeyConditionExpression: "#ty = :val", ExpressionAttributeNames: { "#ty": "topic", }, ExpressionAttributeValues: { ":val": topic, }, }; console.log(params); return await docClient.query(params).promise(); } catch (e) { throw e; } };
问题原因与修复方案
问题核心是DynamoDBClient和DynamoDBDocumentClient的参数格式不兼容:
- 原生
DynamoDBClient要求ExpressionAttributeValues必须使用DynamoDB的类型格式(比如{ S: 'Dynamo' }),不能直接传普通JavaScript类型。 DynamoDBDocumentClient则和v2的DocumentClient用法一致,支持直接传普通JavaScript类型,内部会自动完成类型转换。
针对极简示例的修复
示例中注释掉了正确的dynamoDocClient.send调用,改用原生DynamoDBClient发送请求,导致参数格式不匹配。恢复注释的代码即可解决:
return await dynamoDocClient.send(new QueryCommand(params));
针对实际v3代码的检查与修复
当前代码写法理论上可以正常运行,但需要确认以下两点:
TABLE_NAME已正确定义,没有出现undefined的情况。topic的值是有效字符串,而非undefined或其他非字符串类型,确保DynamoDBDocumentClient能正常完成类型转换。
如果一定要使用原生DynamoDBClient,则需要手动将参数转换为DynamoDB类型格式,示例:
ExpressionAttributeValues: { ':val': { S: topic } }
内容的提问来源于stack exchange,提问作者Rilcon42
相关产品推荐
相关产品推荐

