【问题标题】:DynamoDB : The provided key element does not match the schemaDynamoDB:提供的关键元素与架构不匹配
【发布时间】:2022-03-16 01:50:17
【问题描述】:

有没有办法根据不是哈希键的字段来获取项目?

例子

我的表用户:id (HashKey), name, email

我想检索电子邮件为“test@mail.com”的用户

如何做到这一点?

我用 boto 试试这个:

user = users.get_item(email='john.doe@gmail.com')

我收到以下错误:

'The provided key element does not match the schema'

【问题讨论】:

    标签: python amazon-web-services amazon-dynamodb boto


    【解决方案1】:

    以下内容适用于 AWS Lambda 环境中的 Node.js AWS 开发工具包:

    这对我来说是一个艰难的过程。我在尝试使用 getItem 方法时遇到了这个问题。无论我尝试什么,我都会继续收到此错误。终于在AWS论坛上找到了解决办法:https://forums.aws.amazon.com/thread.jspa?threadID=208820

    莫名其妙地,明显的解决方案与我能找到的所有 AWS 文档冲突。

    这是对我有用的代码:

    var doc = require('dynamodb-doc');
    var dynamo = new doc.DynamoDB();
    
    var params = { }
    params.TableName = "ExampleTable";
    var key = { "ExampleHashKey": "1" };
    params.Key = key;
    
    dynamo.getItem(params, function(err, data) {
        if (err)
            console.log(err);
        else
            console.log(data)
    });
    

    【讨论】:

    • 谢谢!问题确实是 AWS 文档要求一个编组对象(例如 var key = { "ExampleHashKey": { "S": "1" } }),而实际的 SDK 需要一个普通的 javascript 对象(例如 var key = { "ExampleHashKey": "1" })。 update/updateItem 方法也发生了这种情况
    • DynamoDB 的文档一直是个挑战。我认为这里问题的根本原因是基本 DynamoDB 客户端和更高级别的 Document Client 之间的区别。基本客户端使用 AttributeValues,例如var key = { S: { name: 'joe' } } 而 Document Client 使用本机 JavaScript 对象,例如var key = { name: 'joe' }.
    • 在 Ruby 文档的情况下,docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/… 似乎很困惑,因为 Aws::DynamoDB::Client 类的示例包含描述封送值的相同问题,但实际期望处理典型哈希
    • ExampleHashKey 是数据条目的id。旁边的1代表什么
    • 注意:显然此解决方案不再有效,现在 AWS 开发工具包的行为符合文档,因此您的示例现在以这种形式正确:var key = { "ExampleHashKey": { S: "1"} };
    【解决方案2】:

    要查询不是哈希键的字段,您需要使用全局二级索引 (GSI)。查看this AWS Post 了解有关 GSI 的更多详细信息。

    2015 年 2 月更新:现在可以将 GSI 添加到现有表中。有关详细信息,请参阅Amazon Docs

    可悲的是you cannot add a GSI to an existing DynamoDB table,所以如果你真的需要查询,你需要创建一个新表并移植你的数据。

    来自DynamoDB FAQ

    问:如何为 DynamoDB 表创建全局二级索引?

    必须在创建表时指定与表关联的所有 GSI 时间。此时不能在表后添加GSI 已经被创造了。有关创建表及其的详细步骤 索引,请参阅here。每个表最多可以创建5 global secondary indexes

    如果您不想移植您的数据,您可以考虑创建第二个 DynamoDB 表,其中电子邮件作为哈希键和父记录的哈希值用作对主数据表的查找,但当您可以想象这并不是一个最佳的解决方案,而且它本身就让人头疼的是要让它与你的主表保持同步。

    【讨论】:

    • 谢谢 Wolfwyrd.. 很多事情现在我都清楚了。
    • 这是一个较旧的响应,但以防万一有人找到此答案,现在可以在现有表上创建全局索引。本地索引仍必须在创建时设置。
    【解决方案3】:

    我在发送字符串而不是整数时也遇到了这个错误。

    当然,这是我写入数据库而不是读取数据的时候。

    【讨论】:

    • 在我使用 baopham/laravel-dynamodb 的情况下,我必须使用(字符串)和(整数)创建一个显式类型:$model = ModelData::where('PartitionKey', (string)$SearchPartitionKey)->where('SortKey',(integer)$SearchSortKey)->get();
    【解决方案4】:

    我的表上有一个分区键和一个排序键。

    我只用分区键查询它,我得到了这个错误。

    显然,查询复合键修复了它。

    【讨论】:

      【解决方案5】:

      我在 Java 中遇到了这个错误,因为我使用了 @DynamoDBHashKey 注释作为 RANGE 键。我不得不使用 @DynamoDBRangeKey 注释来代替我的对象的 id。

      【讨论】:

        【解决方案6】:

        我在我的 Java 应用程序中遇到了这个错误,因为我不小心在我的 DAO 类中注释了两个 Range 键 (@DynamoDBRangeKey),而实际上应该只有一个。我将新添加的注释更改为@DynamoDBAttribute,并解决了它。

        【讨论】:

          【解决方案7】:

          我的 AWS Lambda 函数出现此错误,因为我的参数是 BigInt,需要转换为 Number。我改变了这个:

          let data = await docClient.get({ TableName: "items", Key: { "accountid": accountId, "itemid": itemId } }).promise();
          

          ...到这个:

          let data = await docClient.get({ TableName: "items", Key: { "accountid": Number(accountId), "itemid": Number(itemId) } }).promise();
          

          【讨论】:

            【解决方案8】:

            如果它对刚开始使用 DynamoDB 的其他人有所帮助,我在尝试使用 GetItemCommand 并且仅在具有复合主键的表上提供分区键时遇到此错误。

            另外为排序键指定一个值以检索与该组合匹配的单个记录,或者切换到QueryCommand 以返回仅匹配分区键的任何内容,而不管排序键如何。

            【讨论】:

              猜你喜欢
              • 2021-08-26
              • 2019-07-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-09-14
              • 1970-01-01
              • 1970-01-01
              • 2016-07-30
              相关资源
              最近更新 更多