【问题标题】:AWS is complaining about a parameter being the wrong type, when it really is notAWS 抱怨参数类型错误,但实际上不是
【发布时间】:2019-03-17 07:58:18
【问题描述】:

我是 AWS 的新人。就像 3 天新的一样。我在 Amazon 的一个教程中找到了与 DynamoDB 表交互的 lambda 函数的代码。该示例仅为 GET 请求提供测试 JSON,这将导致数据库中的项目列表,但代码本身支持 PUT、POST 和 DELETE,用于包含表的完整 CRUD。

所以,我创建了一个名为“Users”的 DynamoDB 表,其分区键 CompanyId 是一个字符串,以及一个排序键 Email 这也是一个字符串。

然后我创建了一个 lambda 函数并添加了教程中的代码:

console.log('Loading function');

const doc = require('dynamodb-doc');

const dynamo = new doc.DynamoDB();

/**
 * Demonstrates a simple HTTP endpoint using API Gateway. You have full
 * access to the request and response payload, including headers and
 * status code.
 *
 * To scan a DynamoDB table, make a GET request with the TableName as a
 * query string parameter. To put, update, or delete an item, make a POST,
 * PUT, or DELETE request respectively, passing in the payload to the
 * DynamoDB API as a JSON body.
 */
exports.handler = (event, context, callback) => {
    console.log('Received event:', JSON.stringify(event, null, 2));

    const done = (err, res) => callback(null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
        headers: {
            'Content-Type': 'application/json',
        },
    });

    switch (event.httpMethod) {
        case 'DELETE':
            dynamo.deleteItem(JSON.parse(event.body), done);
            break;
        case 'GET':
            dynamo.scan({ TableName: event.queryStringParameters.TableName }, done);
            break;
        case 'POST':
            console.log(event.body);
            dynamo.putItem(JSON.parse(event.body), done);
            break;
        case 'PUT':
            dynamo.updateItem(JSON.parse(event.body), done);
            break;
        default:
            done(new Error(`Unsupported method "${event.httpMethod}"`));
    }
};

在测试了 GET 代码(并获得了一个长度为 0 的项目列表,因为我的表是空的)之后,我决定创建一个测试,将一个项目添加到数据库中。我创建了一个名为 PostTest 的测试事件,测试内容如下:

{
  "httpMethod": "POST",
  "body": "{\"Item\": {\"CompanyId\": {\"S\": \"test-company-id\"},\"FirstName\": {\"S\": \"John\"}, \"LastName\": {\"S\": \"Doe\"}, \"Email\": {\"S\": \"john.doe@gmail.com\"}, \"Password\": {\"S\": \"password\"}}, \"TableName\": \"Users\"}"
}

我想指出的是,CompanyId 被设置为“S”,或者换句话说,设置为字符串类型。

当我运行测试时,我得到了以下响应:

{
  "statusCode": "400",
  "body": "One or more parameter values were invalid: Type mismatch for key CompanyId expected: S actual: M",
  "headers": {
    "Content-Type": "application/json"
  }
}

日志的内容是:

START RequestId: 294a7414-cde5-11e8-a7bd-bd58483e1612 Version: $LATEST
2018-10-12T06:07:56.232Z    294a7414-cde5-11e8-a7bd-bd58483e1612    Received event: {
  "httpMethod": "POST",
  "body": "{\"Item\": {\"CompanyId\": {\"S\": \"test-company-id\"},\"FirstName\": {\"S\": \"John\"}, \"LastName\": {\"S\": \"Doe\"}, \"Email\": {\"S\": \"john.doe@gmail.com\"}, \"Password\": {\"S\": \"password\"}}, \"TableName\": \"Users\"}"
}
2018-10-12T06:07:56.232Z    294a7414-cde5-11e8-a7bd-bd58483e1612    {"Item": {"CompanyId": {"S": "test-company-id"},"FirstName": {"S": "John"}, "LastName": {"S": "Doe"}, "Email": {"S": "john.doe@gmail.com"}, "Password": {"S": "password"}}, "TableName": "Users"}
END RequestId: 294a7414-cde5-11e8-a7bd-bd58483e1612
REPORT RequestId: 294a7414-cde5-11e8-a7bd-bd58483e1612  Duration: 173.04 ms Billed Duration: 200 ms     Memory Size: 512 MB Max Memory Used: 30 MB

我对响应中的错误感到困惑:

Type mismatch for key CompanyId expected: S actual: M

如果您查看日志,请求正文中的 CompanyId 设置为“S”。 “M”从何而来?我做错了什么?

不用说,我的表中没有添加任何项目。

【问题讨论】:

    标签: aws-lambda amazon-dynamodb


    【解决方案1】:

    我不知道dynamodb-doc 的背后是什么,但aws-sdk 有类似的问题。

    给定const AWS = require('aws-sdk'),您可能有两个连接器。示例:

    • const DDB = new AWS.DynamoDB();
    • const DC = new AWS.DynamoDB.DocumentClient();

    当使用DDB 连接时,您必须按照您的方式格式化项目,使用类型。

    当使用 DocumentClient (DC) 时,类型会被推断出来,因此您不必显式提供类型。试试这样的:

    {
      "httpMethod": "POST",
      "body": "{\"Item\": {\"CompanyId\": \"test-company-id\",\"FirstName\": \"John\", \"LastName\": \"Doe\", \"Email\": \"john.doe@gmail.com\", \"Password\":  \"password\"}, \"TableName\": \"Users\"}"
    }
    

    使用DC,CompanyId 被正确推断为地图:{\"S\": \"test-company-id\"}。垃圾进垃圾出。 :)

    【讨论】:

    • 科斯汀,谢谢。两个建议都奏效了。我在 DocumentClient 上阅读过,我喜欢它。我知道我可能会在某些时候遇到它的限制,但我认为现在它可以满足我的需要。
    • 不客气,蒂比。我使用 DocumentClient 已经有一段时间了,我对此非常满意。我在使用 StringSets 时只遇到了一些问题,使用 dynamodb-local 和 AWS 进行测试之间存在一些差异。有需要的时候再提一个问题...同时使用 Document Client,它更简单;)
    猜你喜欢
    • 2023-03-04
    • 2015-07-02
    • 1970-01-01
    • 2021-07-18
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多