如何修复DynamoDB中「提供的键元素与架构不匹配」错误?
解决DynamoDB batchGetItem 键不匹配错误
问题场景
我在应用中使用DynamoDB,需要获取与数组中某一键匹配的条目,代码如下:
exports.handler = async (event) => { try { const IDs = [ {"profileID": {"S": "my_first_id"}}, {"profileID": {"S": "my_second_id"}} ] const postsResult = await db.batchGetItem({ RequestItems: { 'Feed': { Keys: IDs } } }).promise(); return { statusCode: 200, body: JSON.stringify(postsResult), }; } catch (err) { console.log(err) return { error: err } } }
执行后遇到错误:
The provided key element does not match the schema
表的GraphQL架构定义如下:
type Feed @model @auth(rules: [{allow: private}]){ profileID: String @index(name: "feedByProfileID") type: String postID: String shareID: String likeID: String commentID: String replyID: String }
错误原因
- 用Amplify的
@model指令创建的DynamoDB表,默认会自动生成**id作为主键(Partition Key)**,你代码中用profileID作为查询键,不符合表的主键结构,因此触发错误。 profileID只是你定义的二级全局索引(GSI),不是表的主键,而batchGetItem要求必须使用表的主键(含分区键和排序键,若存在)来查询,无法直接使用二级索引键。
解决方案
方案1:通过二级索引执行Query查询
针对二级索引feedByProfileID,使用query方法查询每个profileID对应的条目,可并行执行多个查询提高效率:
exports.handler = async (event) => { try { const targetProfileIds = ["my_first_id", "my_second_id"]; // 为每个profileID创建query请求并并行执行 const queryTasks = targetProfileIds.map(profileId => db.query({ TableName: 'Feed', IndexName: 'feedByProfileID', KeyConditionExpression: 'profileID = :profileVal', ExpressionAttributeValues: { ':profileVal': { S: profileId } } }).promise() ); const queryResults = await Promise.all(queryTasks); // 合并所有查询结果中的条目 const allPosts = queryResults.flatMap(result => result.Items); return { statusCode: 200, body: JSON.stringify(allPosts), }; } catch (err) { console.log(err); return { error: err.toString() }; } };
方案2:修改表结构将profileID设为主键
如果你需要用profileID作为主键进行batchGetItem查询,可以修改GraphQL schema,将profileID标记为@id(替代默认生成的id):
type Feed @model @auth(rules: [{allow: private}]){ profileID: String @id @index(name: "feedByProfileID") type: String postID: String shareID: String likeID: String commentID: String replyID: String }
修改后重新部署Amplify后端,表的主键将变为profileID,此时你的原batchGetItem代码即可正常运行。
注意:修改主键结构会导致表重建,若已有生产数据,需提前做好数据迁移或备份。
内容的提问来源于stack exchange,提问作者Besart
相关产品推荐
相关产品推荐

