关键元素与 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',
},
};
我有一个使用 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',
},
};