DynamoDB - 键元素与模式不匹配

72

我正在尝试更新DynamoDB表+ Users +中的一项。我尝试了许多不同的方法,但始终收到相同的错误消息:

提供的关键元素与模式不匹配

创建项目以及查询都可以,但更新则不行。当我在DynamoDB上检查时,用户已经创建成功:

{
  "email": "test@email.com",
  "password": "123",
  "registration": 1460136902241,
  "verified": false
}

这是表格信息:

  • 表名: Users
  • 主分区键: email (字符串)
  • 主排序键: registration (数字)

以下是代码(从 Lambda 调用):

exports.handler = function(event, context)
{
    var AWS = require("aws-sdk");


    var docClient = new AWS.DynamoDB.DocumentClient();

    var params = {
        TableName: "Users",
        Item:{
            email: "test@email.com",
            password: "123",
            verified: false,
            registration: (new Date()).getTime(),
        }
    };

    // Create the user.

    docClient.put(params, function(err, data)
    {
        if (err)
        {
            context.fail("Put failed...");
            return;
        }

        var params = {
            TableName: "Users",
            Key: { email : "test@email.com" },
            AttributeUpdates: {
                verified: {
                    Action: "PUT",
                    Value: true
                }
            }
        };

        // Update the user.
        docClient.update(params, function(err, data)
        {
            if (err)
            {
                console.log(JSON.stringify(err));
                context.fail(JSON.stringify(err));
                return;
            }
            context.succeed("User successfully updated.");
        });


    });

};

你有没有想过我的代码可能出了什么问题?

7个回答

135

您只提供了主键的一半。您的主键是分区键和排序键的组合。在更新参数中,您需要在Key属性中包括排序键。


1
可以了,谢谢!但是只使用电子邮件地址作为主键是否可行? - user6178502
可能是键名中有拼写错误,这在我的情况下发生过。 - Nazeel
11
如果你仍然想只使用主键进行查询,你需要使用“query”方法而不是“get”方法。在这种情况下,你只能提供KeyConditionExpression:“PK = xxx”。 - Dmitry Zlykh
1
我的表中没有范围键,我提供了分区键,但是在调用deleteItem时出现了这个错误。还有其他可能导致这个错误的情况吗? - Azamat Abdullaev
@MarkB 我使用了文档。我把它添加在这里,因为即使在查阅文档并使用带有分区键和二级键的复合键的简单对象后,它仍然无法正常工作。你原来的答案非常有道理。一个旧语法或新语法的例子对任何语言,Java或JS都会有所帮助。我升级到v3,然后带有分区键和二级键的简单对象就可以正常工作了。 - Mark A
显示剩余4条评论

24

对于其他面临相同问题但上述答案未能解决的人,最好再次检查正在更新的值的数据类型。在我的情况下,主键需要一个数字,而我却试图用字符串进行更新。我太傻了。


2
我也遇到了一个愚蠢的问题。我的表格是用复合键创建的(即主键和排序键)。而实际上,我只想要一个主键体验。吸取教训——提前规划! - crftr

6
我的问题是关于Node SDK删除操作的,文档中要求以以下格式提供:
... {Key: {'id': {S: '123'}}} ...

这似乎与aws-sdk ^2.1077.0不兼容。以下代码可行:

... {Key: {'id': '123'}} ...

你救了我,免去了又一天的调试,谢谢! - Yassine Sedrani

1
我正在使用BatchGetItem,然后将其流式传输到BatchWriteItem(Delete)。DeleteItem不喜欢从对象中获取所有属性,而只需要分区和排序键。
收集所有答案:
  • 属性名称不匹配
  • 属性类型不匹配
  • 提供了一半的键
  • 多余的附加键

1

面对这个问题时,我的检查清单:

  1. 检查您的密钥名称和类型是否与数据库中的相应内容相符。
  2. 使用相应的属性使其明确。例如,在Java中使用@DynamoDBHashKey(attributeName =“userId”)表示名为userId的分区键。
  3. 确保您的类中只有一个字段或getter标记为分区键。

如果您知道更多,请在评论中添加。


1
  • 假设您正在NodeJS中使用"@aws-sdk/client-dynamodb"

  • 如果您的表(ex. UserPostTable)中同时具有排序键(例如post_id)和范围键(例如user_id),并且如果您正在使用其他属性(例如image_url)更新此表,则需要同时指定排序键和范围键。

  • 您需要同时指定排序键和范围键

      const updateParams = {
    TableName: process.env.TABLE_NAME,
    Key: {
      post_id: { S: post_id },
      user_id: { S: user_id },
    },
    UpdateExpression: "SET image_url = :url",
    ExpressionAttributeValues: { ":url": { S: image_url } },};const updateCommand = new UpdateItemCommand(updateParams);
    

0
对于这个错误,
The provided key element does not match the schema

这里可能存在两个问题:

  1. 您只提供了主键的一部分。对于主键,您必须提供所有属性。例如,对于简单主键,您只需要为分区键提供一个值。对于复合主键,您必须同时为分区键和排序键提供值。
  2. 字段的值应符合表格的适当数据类型。最好再次检查传递的值的数据类型。也许,您将主键定义为数字,但在getItem调用中传递的是字符串值。

希望能有所帮助。

如果还可能有其他原因,请添加更多内容。


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