aws dynamodb
by Sam Williams
通过山姆·威廉姆斯
如何使用AWS Lambda将DynamoDB集成到您的API中 (How to Integrate DynamoDB into your API using AWS Lambda)
In the first part of this tutorial, we created an API which passed requests through to a Lambda which returned the top tv show or movie for that genre. Now we’re going to use DynamoDB to allow users to vote for their favourite genre.
在本教程的第一部分中 ,我们创建了一个API,该API将请求传递给Lambda,该Lambda返回该类型的顶级电视节目或电影。 现在,我们将使用DynamoDB来允许用户为自己喜欢的类型投票。
If you’ve not read the first part of this series, then check it out here!
如果您尚未阅读本系列的第一部分, 请在此处查看 !
DynamoDB (DynamoDB)
DynamoDB is a non-relational database created by Amazon that we can use to store the users’ votes. It’s also great, because we can access it easily using the aws-sdk which Lambdas have preinstalled.
DynamoDB是由Amazon创建的非关系数据库,我们可以用来存储用户的投票。 这也很棒,因为我们可以使用aws-sdk轻松访问它 Lambdas已预安装。
The first thing we need to do is to create a table to store the movie votes. Navigate to DynamoDB in AWS and click “Create table”.
我们需要做的第一件事是创建一个表来存储电影票。 导航到AWS中的DynamoDB,然后单击“创建表”。
On the next page, we will name our table and provide a primary key. The primary key needs to be unique so we don’t have two records with the same key. We can call the table “movie-api” and set the primary key to “movie-genre”, as each movie should only appear once in each genre.
在下一页上,我们将命名表并提供主键。 主键必须是唯一的,因此我们没有两个记录具有相同的键。 我们可以将表格称为“ movie-api”,并将主键设置为“ movie-genre”,因为每部电影在每种流派中只能出现一次。
We’ve now set up all that we need to set up in DynamoDB so we can go back into our code.
现在,我们已经设置了在DynamoDB中需要设置的所有内容,因此我们可以返回到代码中。
添加Dynamo处理程序 (Adding a Dynamo handler)
Getting and putting data into a Dynamo table is done using the documentClient
on aws-sdk, but the structure of the requests is very specific. To make our lives easier, we can make a Dynamo handler to do all of the formatting.
使用aws-sdk上的documentClient
将数据获取并放入Dynamo表中,但是请求的结构非常具体。 为了使生活更轻松,我们可以使Dynamo处理程序进行所有格式化。
Start by creating a new file called “dynamo.js” in the “movieAPI” Lambda. In this file we start by requiring aws-sdk and creating our documentClient
.
首先在“ movieAPI” Lambda中创建一个名为“ dynamo.js”的新文件。 在此文件中,我们首先需要aws-sdk并创建我们的documentClient
。
const AWS = require('aws-sdk');
let documentClient = new AWS.DynamoDB.DocumentClient({ 'region': 'eu-west-1'});
We now want to create and export a class that has three methods on it: a get
, a write
, and an update
.
现在,我们要创建并导出一个具有三种方法的类: get
, write
和update
。
module.exports = class DB { get(key, value, table) {} write(ID, data, table) {} async increment(ID, table) {}}
We’ll start by creating our get
method. The first thing we need to do is to check that we have a valid key
, value
, and table
.
我们将从创建get
方法开始。 我们需要做的第一件事是检查我们是否具有有效的key
, value
和table
。
if (!table) throw 'table needed';if (typeof key !== 'string') throw `key was not string and was ${JSON.stringify(key)} on table ${table}`;if (typeof value !== 'string') throw `value was not string and was ${JSON.stringify(value)} on table ${table}`;
Because we want this method to be promise-based, we need to return a new Promise
.
因为我们希望该方法基于promise,所以我们需要返回一个new Promise
。
return new Promise((resolve, reject) => {})
To get data from Dynamo, we need to pass a set of parameters to the document client. These params need to include TableName
and Key
.
要从Dynamo获取数据,我们需要将一组参数传递给文档客户端。 这些参数需要包含TableName
和 Key
。
let params = { TableName: table, Key: {[key]: value}};
We pass these params to documentClient
and then reject
if there is an error or resolve
if there isn’t.
我们将这些参数传递给documentClient
然后reject
如果有错误或resolve
如果没有。
documentClient.get(params, function(err, data) { if (err) { console.log(`There was an error fetching the data for ${key} ${value} on table ${table}`, err); return reject(err); } return resolve(data.Item);});
A similar process is done for the write
method. We check that the parameters are valid, create the parameters, and pass them to documentClient
.
对write
方法执行类似的过程。 我们检查参数是否有效,创建参数 ,并将其传递给documentClient
。
return new Promise((resolve, reject) => { if (typeof ID !== 'string') throw `the id must be a string and not ${ID}`; if (!data) throw "data is needed"; if (!table) throw 'table name is needed';
let params = { TableName: table, Item: { ...data, ID: ID } };
documentClient.put(params, function(err, result) { if (err) { console.log("Err in writeForCall writing messages to dynamo:", err); console.log(params); return reject(err); } console.log('wrote data to table ', table) return resolve({ ...result.Attributes, ...params.Item }); });});
The increment
method is a lot easier. To increment, we try getting the data for that key, increase the count by one, and then write it back to the database. If we can’t get the data, or if there is no count on the data, then we assume that we need to set the count to 0.
increment
方法要容易得多。 要递增,我们尝试获取该键的数据,将计数增加一,然后将其写回到数据库。 如果无法获取数据,或者数据上没有计数,则假定需要将计数设置为0。
async increment(ID, table) { if (!table) throw 'table needed'; if (!ID) throw 'ID needed'; let data; try { data = await this.get('movie-genre', ID, table); if (!data.count) throw 'no count in data' } catch (err) { data = { "movie-genre": ID, count: 0 }; }; let newData = { ...data, count: data.count + 1 }; return this.write(ID, newData, table);}
修改我们的Lambda (Modifying our Lambda)
Now we have an easy way to get, write, and update our Dynamo table. We can use this to allow our users to vote. Inside “index.js”, we first need to import our new Dynamo class and create an instance of it.
现在,我们有一种简单的方法来获取,编写和更新Dynamo表。 我们可以使用它来允许我们的用户投票。 在“ index.js”内部, 我们首先需要导入新的Dynamo类并创建一个实例。
const DB = require('./dynamo');const Dynamo = new DB();
Now, inside of our putMovie
we can add the logic to allow users to vote. The two things we need to get are movie
from the body and genre
from the path parameters. We then combine these to create our movie-genre
ID. This then gets passed into Dynamo.increment
with a table name of movie-api
and our putMovie
is complete.
现在,在我们的putMovie
我们可以添加允许用户投票的逻辑。 我们需要获得的两件事是来自主体的movie
和来自路径参数的genre
。 然后,我们结合这些来创建我们的movie-genre
ID。 然后,将其以表名movie-api
传递到Dynamo.increment
,并且我们的putMovie
已完成。
const putMovie = async event => { let { movie } = JSON.parse(event.body); let genre = event.pathParameters.genre; let ID = `${movie}-${genre}`; return Dynamo.increment(ID, 'movie-api')}
To get this to work when we receive the Put
request, we need to slightly modify our base handler function.
当我们收到Put
时,要使其工作 请求,我们需要稍微修改我们的基本处理函数。
if (event.httpMethod === 'PUT') { let response = await putMovie(event) return done(response);}
Because we’ve added AWS to our Lambda, we need to run npm init
and then npm install — save aws-sdk
while in the Lambda folder. This can be done locally and uploaded, or done using Cloud9.
因为我们已经将AWS添加到Lambda中,所以我们需要运行npm init
,然后再进行npm install — save aws-sdk
在Lambda文件夹中。 这可以在本地完成并上载,也可以使用Cloud9完成。
添加API网关方法 (Adding the API Gateway method)
With the new function, we can add a new method to our API. In API Gateway, we can select our “movieAPI” and then select “/movies/{genre}”. Click “Actions” -> “Create Method” and choose to add a “PUT” method.
使用新功能,我们可以向API添加新方法。 在API网关中,我们可以选择“ movieAPI”,然后选择“ / movies / {genre}” 。 点击“操作” - >“○d创建冰毒”,并选择添加“PUT”方法。
This “PUT” can be directed at our “movieAPI”, and tick “Use Lambda Proxy Integration”. Once saved we can test it out. On the method we can click “TEST” and enter a genre and a body containing a movie. When we click “TEST” we get a response containing the movie and new count. As this is the first vote, the count will be 1.
该“ PUT”可以直接指向我们的“ movieAPI” ,然后勾选“使用Lambda代理集成”。 保存后,我们可以对其进行测试。 在方法上,我们可以单击“测试”,然后输入流派和包含电影的正文。 当我们单击“测试”时,我们将收到包含电影和新计数的响应。 由于这是第一次投票,因此计数为1。
Running the test a second time will now increment the votes for this movie by one.
现在,第二次运行测试会将这部电影的票数增加一。
修改GET方法 (Modifying the GET method)
Now that we have a new voting system, we can update our “GET” to use this new data. We need to get all of the movies that are in the requested genre and list them in order of votes.
现在有了新的投票系统,我们可以更新“ GET” 使用此新数据。 我们需要获取所请求类型的所有电影,并按投票顺序列出它们。
We first need to make a new dynamo method. This method will scan each of the entries and pick out the ones that match our criteria.
我们首先需要制作一种新的发电机方法。 此方法将扫描每个条目并挑选出符合我们标准的条目。
scan(key, value, table) { return new Promise((resolve, reject) => { let params = { TableName: table, FilterExpression: `${key} = :value`, ExpressionAttributeValues: { ':value': value } }; documentClient.scan(params, function(err, data) { if (err) reject(err); resolve(data); }); });}
We can now modify our getMovie
function to use this new Dynamo method. We need to pass the genre, selected movie, and current count.
现在我们可以修改我们的getMovie
函数来使用这种新的Dynamo方法。 我们需要传递流派,选定的电影和当前计数。
const getMovie = async event => { let genre = event.pathParameters.genre; let data = await Dynamo.scan('genre', genre, 'movie-api'); let result = data.Items.sort((a,b) => b.count - a.count); result = result.map(({count, ID, genre})=> { return {count, ID, genre}}); return data;}
The last thing to do is to add an await
before out getMovie
function so that it handles the async database scan.
最后要做的是在getMovie
之前添加一个await
功能,以便它处理异步数据库扫描。
let response = await getMovie(event);
测试中 (Testing)
When we hit this new “GET” endpoint we receive an ordered list of all of the movies in the database.
当我们点击这个新的“ GET”端点时,我们会收到数据库中所有电影的有序列表。
[ { "count": 2, "ID": "Desperado (1995)-action", "genre": "action" }, { "count": 1, "ID": "Team America (2004)-action", "genre": "action" }]
摘要 (Summary)
We’ve now built an API that can handle “GET” and “PUT” requests, storing and retrieving data from a Dynamo database. You can also reuse a lot of the Dynamo class code for other APIs that work with Dynamo.
现在,我们已经构建了一个API,该API可以处理“ GET”和“ PUT”请求,并从Dynamo数据库中存储和检索数据。 您还可以将许多Dynamo类代码重用于与Dynamo一起使用的其他API。
要练习吗? (Want some practice?)
If you’ve enjoyed this, then why not try to implement a similar setup for tv shows? If you do, then let me know how it goes!
如果您喜欢它,那为什么不尝试为电视节目实现类似的设置呢? 如果您这样做,那么让我知道它的进展!
You can also improve this API by making sure that Desperado (1995)
and desperado (1995)
both count towards the same movie, or only allow a certain format of movie title.
您还可以通过确保Desperado (1995)
和desperado (1995)
都计入同一部电影,或仅允许使用某种格式的电影标题来改进此API。
If you’ve liked this, then make sure to give it a clap and subscribe for more Amazon tutorials and guides. See you in the next article and Keep Coding!
如果您喜欢此功能,请确保对其鼓掌并订阅更多Amazon教程和指南。 在下一篇文章中见,并继续编码!
翻译自: https://www.freecodecamp.org/news/building-an-api-with-lambdas-and-api-gateway-part-2-7c674a0eb121/
aws dynamodb