Lambda更新DynamoDB遇ValidationException:键元素与Schema不匹配求因
DynamoDB更新嵌套列表时遇到ValidationException的问题解决
嘿,我来帮你揪出这个问题的根源——你碰到的ValidationException(提示键元素与schema不匹配)其实是因为在ExpressionAttributeNames里的写法犯了个常见错误,咱们一步步拆解:
首先,你的DynamoDB数据结构是这样的:
{ "userId":"amzn1.ask.account.XYZ", "mapAttr":{ "name":"John", "colors":[ "yellow", "white" ] } }
你尝试用来更新colors列表的代码是:
var docClient = new AWS.DynamoDB.DocumentClient({ apiVersion: "2012-08-10" }); var params = { TableName: "myTable", Key: { userId: userId }, UpdateExpression: "SET #mapAttr = list_append(#mapAttr, :entry)", ExpressionAttributeNames: { "#mapAttr": "mapAttr.colors" }, ExpressionAttributeValues: {":entry": ["blue"] }, ReturnValues: "UPDATED_NEW" }; docClient.update(params, function(err, data) { if (err) { console.error( "Unable to update item. Error JSON:", JSON.stringify(err, null, 2) ); } else { console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2)); } });
收到的报错是:
无法更新条目。错误JSON:{ "message": "提供的键元素与schema不匹配", "code": "ValidationException" }
问题原因
核心问题出在ExpressionAttributeNames的写法上:DynamoDB的DocumentClient不支持在属性名占位符(比如#mapAttr)里直接用点分隔嵌套属性(像"mapAttr.colors"这种写法)。当你这么写的时候,DynamoDB会把整个"mapAttr.colors"当成一个单一的顶层属性名,但你的表结构里根本没有这个顶层属性,同时这种错误的属性名解析会导致它无法正确匹配你Key里的userId对应的条目结构,最终抛出“键元素与schema不匹配”的异常。
修复方案
你需要把嵌套路径的处理拆开来,有两种方式:
方式1:用多个属性名占位符分别替换嵌套层级
如果需要用占位符避免关键字冲突,可以分别为mapAttr和colors定义占位符:
var docClient = new AWS.DynamoDB.DocumentClient({ apiVersion: "2012-08-10" }); var params = { TableName: "myTable", Key: { userId: userId }, UpdateExpression: "SET #ma.#c = list_append(#ma.#c, :entry)", ExpressionAttributeNames: { "#ma": "mapAttr", "#c": "colors" }, ExpressionAttributeValues: {":entry": ["blue"] }, ReturnValues: "UPDATED_NEW" }; docClient.update(params, function(err, data) { if (err) { console.error( "Unable to update item. Error JSON:", JSON.stringify(err, null, 2) ); } else { console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2)); } });
方式2:直接在UpdateExpression里写嵌套路径
因为mapAttr和colors都不是DynamoDB的关键字,你可以直接省略ExpressionAttributeNames,简化代码:
var docClient = new AWS.DynamoDB.DocumentClient({ apiVersion: "2012-08-10" }); var params = { TableName: "myTable", Key: { userId: userId }, UpdateExpression: "SET mapAttr.colors = list_append(mapAttr.colors, :entry)", ExpressionAttributeValues: {":entry": ["blue"] }, ReturnValues: "UPDATED_NEW" }; docClient.update(params, function(err, data) { if (err) { console.error( "Unable to update item. Error JSON:", JSON.stringify(err, null, 2) ); } else { console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2)); } });
这两种写法都能正确识别嵌套的colors列表,完成追加元素的操作。
内容的提问来源于stack exchange,提问作者qbas1409
相关产品推荐
相关产品推荐

