DynamoDB写入数据时触发Cannot read properties of undefined (reading '0')错误
解决DynamoDB UpdateItem时的TypeError: Cannot read properties of undefined (reading '0')错误
问题根源
你当前使用的是**@aws-sdk/client-dynamodb**(低级DynamoDB客户端),这个客户端要求必须手动指定每个属性的DynamoDB数据类型(如{ S: "字符串值" }、{ N: "数字值" })。你误以为可以直接传入原始字符串/数字——这是**@aws-sdk/lib-dynamodb**(带DocumentClient的高级客户端)的特性,低级客户端不支持自动类型序列化。
当低级客户端尝试处理你传入的原始值时,会试图读取值的类型标识结构,导致抛出Cannot read properties of undefined (reading '0')错误。
解决方案(推荐:使用DocumentClient)
DocumentClient会自动帮你处理数据类型的序列化/反序列化,无需手动包装属性值,代码更简洁易维护。
- 安装依赖(如果未安装):
npm install @aws-sdk/lib-dynamodb @aws-sdk/client-dynamodb
- 修改客户端初始化代码:
import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { DynamoDBDocumentClient, UpdateCommand } from "@aws-sdk/lib-dynamodb"; // 初始化基础客户端 const dynamoDBClient = new DynamoDBClient({}); // 创建DocumentClient实例(替换你原来的dynamoDB变量) const dynamoDB = DynamoDBDocumentClient.from(dynamoDBClient);
- 你的
initializeProcessing函数无需修改参数结构,直接保留现有代码即可——DocumentClient会自动处理类型转换:
// Initialize the message processing entry const initializeProcessing = async (s3jsonfile, messageId, totalEntries, messageProcessingTableName) => { console.log('S3 Key:', s3jsonfile); console.log('Message Info:', messageId); console.log('Total Entries:', totalEntries); const params = { TableName: messageProcessingTableName, Key: { s3jsonfile, // Partition key messageId // Sort key }, UpdateExpression: 'SET totalEntries = :totalEntries, entriesProcessed = :entriesProcessed, processingStatus = :processingStatus, lastUpdated = :timestamp', ExpressionAttributeValues: { ':totalEntries': totalEntries.toString(), // Ensure this is a string ':entriesProcessed': '0', // Plain string ':processingStatus': '0', // Plain string ':timestamp': new Date().toISOString() // ISO string for date } }; console.log('Parameters for UpdateCommand:', JSON.stringify(params, null, 2)); // Detailed logging try { await dynamoDB.send(new UpdateCommand(params)); console.log(`Message ${messageId} initialized for ${totalEntries} entries.`); } catch (error) { console.error('Error initializing message processing:', error); console.error('Parameters used:', params); // Log parameters for debugging } };
备选方案(手动指定数据类型)
如果不想切换到DocumentClient,你需要手动为每个属性添加DynamoDB类型标识:
const params = { TableName: messageProcessingTableName, Key: { s3jsonfile: { S: s3jsonfile }, // 明确指定String类型 messageId: { S: messageId } // 明确指定String类型 }, UpdateExpression: 'SET totalEntries = :totalEntries, entriesProcessed = :entriesProcessed, processingStatus = :processingStatus, lastUpdated = :timestamp', ExpressionAttributeValues: { ':totalEntries': { S: totalEntries.toString() }, ':entriesProcessed': { S: '0' }, ':processingStatus': { S: '0' }, ':timestamp': { S: new Date().toISOString() } } };
对你疑问的解答
- 表中无数据不是错误原因:DynamoDB的
UpdateItem本身支持upsert(不存在则创建,存在则更新),只要参数格式正确就能初始化新条目。 - 无需移除排序键:你的表结构(分区键
s3jsonfile+排序键messageId)设计合理,能唯一标识每个SQS消息的处理记录,完全符合业务需求。
内容的提问来源于stack exchange,提问作者Pablo Costa
相关产品推荐
相关产品推荐

