首页 > 解决方案 > 关键元素与 DocumentClient 的架构不匹配

问题描述

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

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

Debug Locally但是,当我使用VS Code 中的“通过 Code Lens”选项在本地运行 Lambda 时,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 区域中创建了一个表,其中配置了非测试代码。DocumentClient我已经确认 http 端点被as being击中dynamodb.us-east-1.amazonaws.com。表名是正确的,我有一个名为的哈希键year和一个名为title. 为什么这不能正确找到密钥?我从AWS 文档中提取了这个示例,创建了一个表来反映密钥是什么并且没有任何运气。

标签: javascriptnode.jsaws-lambdaamazon-dynamodbaws-sdk

解决方案


问题是 Keyyear提供了一个数字值,而表期望它是一个字符串。

2015引号括起来让 Document 知道这是一个字符串,它可以匹配 Dynamo 中的模式。

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

推荐阅读