当从DynamoDB获取项目时出现“提供的关键元素与架构不匹配”的错误。

70

这是表分区键设置 图片描述

表内容 图片描述

当我尝试从表中获取一个项目时,它会打印出这个错误

botocore.exceptions.ClientError: 调用 GetItem 操作时发生错误 (ValidationException): 提供的键元素与模式不匹配

这是我的代码

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('testDynamodb')
response = table.get_item(Key={'userId': "user2873"})
item = response['Item']
print(item)
任何想法?谢谢。
5个回答

134

你的表模式同时定义了哈希键和排序键。在使用DynamoDB GetItem时,你必须提供它们两个,以下是来自文档的摘录:

对于主键,您必须提供所有属性。例如,在具有简单主键的情况下,您只需要为分区键提供一个值。对于复合主键,您必须提供分区键和排序键的值。

因此,根据您的示例,get_item参数应该如下所示:

response = table.get_item(Key={'userId': "user2873", 'createdAt': "1489376547"})

2
你的表模式同时定义了哈希键和分区键——我有点想在后面加上“需要引用”。你能解释一下如何从问题中的代码和图像中判断出来吗? - Michael Scheper
3
@MichaelScheper 实际上,“哈希键”和“分区键”是一样的东西。有趣的是之前没有人注意到这一点。因此应该说:“您的表模式定义了哈希键和排序键。”我会修复这个问题。 - xtx
2
@MichaelScheper 关于你的问题,通过查看第一张图片(更准确地说是Primary partition keyPrimary sort key字段),你可以确定模式具有分区(哈希)键和排序键。 - xtx
是的,现在你已经做出了那个更正(而且现在我已经多玩了一些Dynamo并获得了稍微更多的经验☺),它有意义了。谢谢! - Michael Scheper
1
这是否意味着无法查询此表以获取所有在单个值(某个日期创建的所有用户)下创建的记录? 这似乎很奇怪。(对DynamoDB不熟悉) - Jason Michael
1
@JasonMichael,使用GetItem无法完成此操作,您需要使用Scan(https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html)。请注意,扫描操作意味着读取表中的所有记录,因此它可能只适用于单次使用,但如果您的应用程序需要多次使用,请考虑调整您的表模式。 - xtx

37

还有一件事情可以起作用,就是下面的代码:

from boto3.dynamodb.conditions import Key

result = table.query(
        KeyConditionExpression=Key('userId').eq('user2873')
    )

5

我也遇到了同样的问题。 解决方法是:

在创建表时,只将usrID定义为schema中的Hash键。[我的意思是单一主键]

然后您可以基于usrID调用get item。 如果您在表Schema中定义usrIdcreatedAt作为HashSort键。[我的意思是复合主键]在调用getItem时必须同时提供两者。


0
遇到了相同的错误,但我的问题很容易解决。我的密钥ID(产品ID)在我的lambda函数.py代码中被称为与我的DynamoDB分区键(Product_Id)不同。所以我必须进行一些更改。你在代码和表中的密钥和分区键应该始终匹配。希望这也能对你有所帮助。 :)

-2

我想你不必把所有相关的属性都放在一起。

在我的情况下,我只有一个主键作为列。

const AWS = require('aws-sdk');
const ddb = new AWS.DynamoDB.DocumentClient();

exports.handler = (event, context, callback) => {
  const connectionId = event.requestContext.connectionId;
  deleteConnectionId(connectionId).then(() => {
    callback(null, { statusCode: 200 , message: 'userId deleted'});
  });
};


function deleteConnectionId(connectionId) {
  return ddb
    .delete({ TableName: 'your table name', 
        Key: {
            userId : connectionId.toString() // userId is my PK in this case
         }
    } )
    .promise();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接