简体   繁体   中英

Error when using getItem with DynamoDB with the node aws-sdk library

The following code produces this error message when trying to access my AWS DynamoDB table. The table is called customers and the column is called email with a value of 'james@gmail.com'. I've copied this code straight out of AWS examples available here https://github.com/awsdocs/aws-doc-sdk-examples . Is there anything I'm doing wrong? I've wasted days on this, trying different things :-(

Any help appreciated. Thanks,

Error message

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

NodeJs code

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 table

在此输入图像描述

Another attempt I've also received this error message

{"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 

Update

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

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

Update

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}!`))

Error result

{"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}

2nd EDIT : I have completely missed that you are not using DocumentClient (as pointed out Vladyslav Ulenko), so updated answer below for completeness.


You have two options:

First option use DynamoDB service object with getItem method like this:

...
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 Data (attribute value) types are specified here (look for table Marshalling/Unmarshalling mapping.

Second option is to use DocumentClient . In this scenario you don't have to worry about marshaling and un-marshaling request/response data (DynamoDB value to/from JavaScript type). In this case your code is like this:

...

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);
    }
});
...

I would suggest you go with the DocumentClient instead of DynamoDB' getItem` operation as it completely handles all data conversion!

If you don't you would ALSO need to take care of response data types, eg:

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

not sure if you want to that


3rd EDIT : Now that you have done the above you are getting error:

"The provided key element does not match the schema"

This means that the Key you used is not the same as the key defined on your schema, again from documentation :

For the primary key, you must provide all of the attributes. For example, with a simple primary key, you only need to provide a value for the partition key. For a composite primary key, you must provide values for both the partition key and the sort key.

Check the keys on your Table Details (example) 在此输入图像描述

and make sure you put all keys mentioned there in your key parameter

Again as Vladyslav pointed out in comment section of his answer, if you need to find an item using the attribute that is not your primary key, you need to use scan operation instead of getItem . You can find sample in documentation

You are using DynamoDB like DocumentClient . If you switch your line var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'}); to var docClient = new AWS.DynamoDB.DocumentClient(); , your queries will work.

With plain DynamoDB class instance you should also specify data types of your keys manually, you can find the reference to data types here . However, with DocumentClient class instance, the very class is responsible for data mapping between JS types and DynamoDB types. You can find this info here in the Overview section.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM