DynamoDB批量写入报错:提供的键元素与架构不匹配
问题:批量写入DynamoDB时出现ValidationException错误
我尝试将本地JSON文件(AllFlagsOn.json)中的数据批量写入AWS DynamoDB已有表tableName,使用以下TypeScript代码实现:
if (appProps.accountName === 'star') { new Stack(app, DEV_APP_NAME); jsonFilePath = './bin/AllFlagsOn.json'; const file = fs.readFileSync(jsonFilePath, 'utf-8'); const data = JSON.parse(file); const items = data["ect-feed-status"]; const client = new DynamoDBClient({ region: 'us-east-1'}); const command = new BatchWriteCommand({ RequestItems: { 'tableName': items.map((item: any) => ({ PutRequest: { Item: item.PutRequest.Item, }, })), }, }); client.send(command).then((response) => { console.log("Batch write succeeded: ", response); }) .catch((error) => { console.log("Batch write failed: ", error); }); }
JSON文件内容如下:
{ "tableName": [ { "PutRequest": { "Item": { "FeatureName": { "S": "blah" }, "Active": { "BOOL": true } } } }, { "PutRequest": { "Item": { "FeatureName": { "S": "blahablah" }, "Active": { "BOOL": true } } } }, { "PutRequest": { "Item": { "FeatureName": { "S": "blahblahblah" }, "Active": { "BOOL": true } } } } ] }
执行后收到错误:
Batch write failed: ValidationException: The provided key element does not match the schema
JSON.stringify(command)输出如下:
{"middlewareStack":{},"input":{"RequestItems":{"tableName":[{"PutRequest":{"Item":{"FeatureName":{"S":"blah"},"Active":{"BOOL":true}}}},{"PutRequest":{"Item":{"FeatureName":{"S":"blahblah"},"Active":{"BOOL":true}}}},{"PutRequest":{"Item":{"FeatureName":{"S":"blahblahblah"},"Active":{"BOOL":true}}}}]}},"inputKeyNodes":[{"key":"RequestItems","children":{"children":[{"key":"PutRequest","children":[{"key":"Item"}]},{"key":"DeleteRequest","children":[{"key":"Key"}]}]}}],"outputKeyNodes":[{"key":"UnprocessedItems","children":{"children":[{"key":"PutRequest","children":[{"key":"Item"}]},{"key":"DeleteRequest","children":[{"key":"Key"}]}]}},{"key":"ItemCollectionMetrics","children":{"children":[{"key":"ItemCollectionKey"}]}}],"clientCommand":{"middlewareStack":{},"input":{"RequestItems":{"tableName":[{"PutRequest":{"Item":{"FeatureName":{"M":{"S":{"S":"blah"}}},"Active":{"M":{"BOOL":{"BOOL":true}}}}}},{"PutRequest":{"Item":{"FeatureName":{"M":{"S":{"S":"blahblah"}}},"Active":{"M":{"BOOL":{"BOOL":true}}}}}},{"PutRequest":{"Item":{"FeatureName":{"M":{"S":{"S":"blahblahblah"}}},"Active":{"M":{"BOOL":{"BOOL":true}}}}}]}}}}
表结构描述(Describe Table)输出:
{ "Table": { "AttributeDefinitions": [ { "AttributeName": "FeatureName", "AttributeType": "S" } ], "TableName": "tableName", "KeySchema": [ { "AttributeName": "FeatureName", "KeyType": "HASH" } ], "TableStatus": "ACTIVE", "CreationDateTime": "2022-08-01T15:24:38.112000-05:00", "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "ReadCapacityUnits": 1, "WriteCapacityUnits": 1 }, "TableSizeBytes": 105, "ItemCount": 3, "TableArn": "arn:aws:dynamodb:us-east-1:blahablahg", "TableId": "ididididid", "DeletionProtectionEnabled": false } }
我已核对属性名和数据类型均与表结构匹配,请问问题出在哪里?
解答
问题出在两处:
JSON数据读取不匹配:代码中读取
data["ect-feed-status"],但JSON文件的顶级键是tableName,这会导致items无法正确获取数据,必须把这行改为const items = data["tableName"]。SDK格式兼容错误:你的JSON文件使用了DynamoDB原生类型格式(带
{S: "xxx"}这类标识),但AWS SDK for JavaScript v3的BatchWriteCommand默认期望使用简化的JS原生类型,SDK会自动完成类型映射。从command的序列化输出能看到数据被错误嵌套:"FeatureName":{"M":{"S":{"S":"blah"}}}说明SDK把你原本的类型标识对象当成了普通Map类型处理,导致结构完全不符合表的键架构。
修复方案
方案一:用SDK工具转换格式
引入marshall函数将原生格式数据转换为SDK兼容结构:
import { marshall } from "@aws-sdk/util-dynamodb"; // 其余代码不变 const command = new BatchWriteCommand({ RequestItems: { 'tableName': items.map((item: any) => ({ PutRequest: { Item: marshall(item.PutRequest.Item), // 添加marshall转换 }, })), }, });
方案二:修改JSON为简化格式
去掉JSON中的类型标识,直接使用JS原生类型:
{ "tableName": [ { "PutRequest": { "Item": { "FeatureName": "blah", "Active": true } } }, // 其余条目同理修改 ] }
修改后代码无需额外转换,SDK会自动处理类型映射。
内容的提问来源于stack exchange,提问作者Tiffany Doan
相关产品推荐
相关产品推荐

