关键元素与 DocumentClient 的架构不匹配

Key element does not match the schema with DocumentClient

我有一个使用 AWS Toolkit for Visual Studio Code 创建的 Lambda。我有一个小的 lambda.js 文件,它导出 API 网关事件的处理程序。

const App = require('./app');
const AWS = require('aws-sdk');

exports.handler = async (event, context) => {
    let config = { 
        aws_region: 'us-east-1',
        //endpoint: 'http://localhost:8000',
    };

    let dynamo = new AWS.DynamoDB.DocumentClient();
    let app = new App(dynamo, config, event);

    try {
        let response = await app.run();
        return response;
    } catch(err) {
        return err;
    }
};

app.js 文件代表我的 Lambda 的逻辑。这是为了改进测试。

const AWS = require('aws-sdk');

class App {
    constructor(datastore, configuration, event) {
        this.datastore = datastore;
        this.httpEvent = event;
        this.configuration = configuration;
    }

    async run() {
        AWS.config.update({
            region: this.configuration.aws_region,
            endpoint: this.configuration.endpoint,
        });

        let params = {
            TableName: 'test',
            Key: {
                'year': 2015,
                'title': 'The Big New Movie',
            },
        };
        const getRequest = this.datastore.get(params);

        // EXCEPTION THROWN HERE
        var result = await getRequest.promise();

        let body = {
            location: this.configuration.aws_region,
            url: this.configuration.endpoint,
            data: result
        };

        return {
            'statusCode': 200,
            'body': JSON.stringify(body)
        };
    }
}

module.exports = App;

我可以编写以下 mocha 测试并使其通过。

'use strict';

const AWS = require('aws-sdk');
const chai = require('chai');
const sinon = require('sinon');
const App = require('../app');

const expect = chai.expect;
var event, context;

const dependencies = {
    // sinon.stub() prevents calls to DynamoDB and allows for faking of methods.
    dynamo: sinon.stub(new AWS.DynamoDB.DocumentClient()),
    configuration: {
        aws_region: 'us-west-2',
        endpoint: 'http://localhost:5000',
    },
};

describe('Tests handler', function () {
    // Reset test doubles for isolating individual test cases
    this.afterEach(sinon.reset);

    it('verifies successful response', async () => {
        dependencies.dynamo.get.returns({ promise: sinon.fake.resolves('foo bar')});
        let app = new App(dependencies.dynamo, dependencies.configuration, event);
        const result = await app.run()

        expect(result).to.be.an('object');
        expect(result.statusCode).to.equal(200);
        expect(result.body).to.be.an('string');
        console.log(result.body);
        let response = JSON.parse(result.body);

        expect(response).to.be.an('object');
        expect(response.location).to.be.equal(dependencies.configuration.aws_region);
        expect(response.url).to.be.equal(dependencies.configuration.endpoint);
        expect(response.data).to.be.equal('foo bar');
    });
});

但是,当我 运行 Lambda 通过 VS Code 中的 Code Lens 选项在本地使用 Debug Locally 时,AWS.DynamoDB.DocumentClient.get 调用的结果会引发异常。

{
  "message":"The provided key element does not match the schema",
  "code":"ValidationException",
  ...
  "statusCode":400,
  "retryable":false,
  "retryDelay":8.354173589804192
}

我在 us-east-1 区域创建了一个 table,非测试代码被配置到该区域。我已经确认 DocumentClient 命中的 http 端点是 dynamodb.us-east-1.amazonaws.com。 table 名称是正确的,我有一个名为 year 的散列键和一个名为 title 的排序键。为什么这不能正确找到密钥?我从 AWS documentation 中提取了这个示例,创建了一个 table 来反映密钥是什么,但没有任何运气。

问题是键 year 被提供了一个数字值,而 table 期望它是一个字符串。

2015 括在引号中让文档知道这是一个字符串,它可以与 Dynamo 中的模式匹配。

let params = {
    TableName: 'test',
    Key: {
        'year': '2015',
        'title': 'The Big New Movie',
    },
};