将getItem与DynamoDB和节点aws-sdk库一起使用时出错

时间:2019-03-13 23:09:17

标签: node.js amazon-web-services amazon-dynamodb

当尝试访问我的AWS DynamoDB表时,以下代码生成此错误消息。该表称为客户,该列称为电子邮件,其值为'james@gmail.com'。我直接从https://github.com/awsdocs/aws-doc-sdk-examples上提供的AWS示例中复制了此代码。我做错了什么吗?我在此上浪费了几天,尝试了不同的事情:-(

任何帮助表示赞赏。 谢谢,

错误消息

{"message":"Expected params.Key to be a map","code":"InvalidParameterType","time":"2019-03-13T23:05:59.231Z"}

NodeJs代码

const express = require('express')
const app = express()
const port = 8080
var AWS = require('aws-sdk');

app.get('/test', (req, res) => {

    // Set the region 
    AWS.config.update({region: 'eu-west-1'});

    // Create DynamoDB document client
    var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

    var key = { email: 'james@gmail.com' };

    ddb.getItem({
       TableName: 'customers',
       Key: key
    }, function(err, data) {
        if (err) {
          res.send(err);
        }
        else {
          res.send(data);
        }
    });

});

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

DynamoDB表

enter image description here

另一种尝试 我也收到了此错误消息

{"message":"There were 20 validation errors:\n* InvalidParameterType: Expected params.Key['email'] to be a structure\n* UnexpectedParameter: Unexpected key '0' found in params.Key['email']\n* UnexpectedParameter: Unexpected key '1' found in params.Key['email']\n* UnexpectedParameter: Unexpected key '2' found in params.Key['email']\n* UnexpectedParameter: Unexpected key '3' found in params.Key['email']\n* UnexpectedParameter: Unexpected key '4' found in params.Key['email']\n* UnexpectedParameter: Unexpected key '5' found in params.Key['email']\n* UnexpectedParameter: Unexpected key '6' found in 

更新

 var key = { email: 'james@gmail.com' };

    ddb.getItem({
       TableName: 'customers',
       Key: key
    }, function(err, data) {
        if (err) {
          res.send(err);
        }
        else {
          res.send(data);
        }
    });

更新

const express = require('express')
const app = express()
const port = 8080
var AWS = require('aws-sdk');

app.get('/test', (req, res) => {

    AWS.config.update({region: 'eu-west-1'});
    var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

    var params = {
      TableName: 'customers',
      Key: {
        'email': {S: 'james@gmail.com'}
      },
    };

    ddb.getItem(params, function(err, data) {
        if (err) {
            res.send(err);
        } else {
            res.send(data);
        }
    });

});

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

错误结果

{"message":"The provided key element does not match the schema","code":"ValidationException","time":"2019-03-14T19:26:13.602Z","requestId":"EIGKLLNEJR2DKSET6787JHQLC7VV4KQNSO5AEMVJF66Q9ASUAAJG","statusCode":400,"retryable":false,"retryDelay":46.10177725769697}

2 个答案:

答案 0 :(得分:2)

第二次编辑:我完全想念您没有使用DocumentClient(如Vladyslav Ulenko所指出的那样),因此为确保完整性,下面更新了答案。


您有两个选择:

第一个选项将DynamoDB服务对象与getItem方法一起使用,如下所示:

...
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

var params = {
  TableName: 'customers',
  Key: {
    'email': {S: 'james@gmail.com'} . // <-- pay attention to data type 'S'  
  },
};

ddb.getItem(params, function(err, data) {
    if (err) {
        res.send(err);
    } else {
        res.send(data);
    }
});

DynamoDB数据(属性值)类型指定为here(查找表编组/解组映射。

第二个选项是使用DocumentClient。在这种情况下,您不必担心封送和取消封送请求/响应数据(DynamoDB到/从JavaScript类型的值)。在这种情况下,您的代码如下:

...

var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});


var params = {
 TableName: 'customers',
 Key: {'email': 'james@gmail.com'}
};

docClient.get(params, function (err, data) {
    if (err) {
        res.send(err);
    } else {
        res.send(data);
    }
});
...

我建议,您可以使用DocumentClient而不是DynamoDB' getItem`操作,因为它可以完全处理所有数据转换!

如果不这样做,还需要注意响应数据类型,例如:

data.Items.forEach(function(element, index, array) {
      console.log(element.FristName.S + " " + element.LastName.S);
    });

不确定是否要


第三次编辑: 完成上述操作后,您将得到错误:

"The provided key element does not match the schema"

这意味着您使用的密钥与您在架构上定义的密钥不同,同样来自documentation

  

对于主键,必须提供所有属性。例如,使用简单的主键,您只需为分区键提供一个值。对于复合主键,必须同时提供分区键和排序键的值。

检查表详细信息上的键(示例) enter image description here

并确保将其中提到的所有键都放在键参数中

Vladyslav再次在他的回答的注释部分中指出,如果您需要使用不是主键的属性来查找项目,则需要使用scan操作而不是getItem。您可以在documentation

中找到示例

答案 1 :(得分:1)

您正在使用DynamoDB之类的DocumentClient。如果将行var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});切换为var docClient = new AWS.DynamoDB.DocumentClient();,您的查询将起作用。

对于普通的DynamoDB类实例,您还应该手动指定密钥的数据类型,您可以找到对数据类型here的引用。但是,对于DocumentClient类实例,该类负责JS类型和DynamoDB类型之间的数据映射。您可以在“概述”部分找到此信息here