So integrieren Sie DynamoDB mithilfe von AWS Lambda in Ihre API

Im ersten Teil dieses Tutorials haben wir eine API erstellt, die Anfragen an einen Lambda weiterleitet, der die beste TV-Show oder den besten Film für dieses Genre zurückgibt. Jetzt werden wir DynamoDB verwenden, damit Benutzer für ihr Lieblingsgenre stimmen können.

Wenn Sie den ersten Teil dieser Serie noch nicht gelesen haben, lesen Sie ihn hier!

DynamoDB

DynamoDB ist eine nicht relationale Datenbank, die von Amazon erstellt wurde und in der die Stimmen der Benutzer gespeichert werden können. Es ist auch großartig, weil wir mit aws-sdk einfach darauf zugreifen könnenwelche Lambdas vorinstalliert haben.

Als erstes müssen wir eine Tabelle erstellen, in der die Filmstimmen gespeichert werden. Navigieren Sie in AWS zu DynamoDB und klicken Sie auf "Tabelle erstellen".

Auf der nächsten Seite werden wir unsere Tabelle benennen und einen Primärschlüssel bereitstellen. Der Primärschlüssel muss eindeutig sein, damit wir nicht zwei Datensätze mit demselben Schlüssel haben. Wir können die Tabelle "movie-api" nennen und den Primärschlüssel auf "movie-genre" setzen, da jeder Film in jedem Genre nur einmal erscheinen sollte.

Wir haben jetzt alles eingerichtet, was wir in DynamoDB einrichten müssen, damit wir wieder in unseren Code zurückkehren können.

Hinzufügen eines Dynamo-Handlers

Das Abrufen und Einfügen von Daten in eine Dynamo-Tabelle erfolgt mit documentClienton aws-sdk , die Struktur der Anforderungen ist jedoch sehr spezifisch. Um unser Leben einfacher zu machen, können wir einen Dynamo-Handler erstellen, der die gesamte Formatierung übernimmt.

Erstellen Sie zunächst eine neue Datei mit dem Namen "dynamo.js" im Lambda "movieAPI". In dieser Datei benötigen wir zunächst aws-sdk und erstellen unsere documentClient.

const AWS = require('aws-sdk');
let documentClient = new AWS.DynamoDB.DocumentClient({ 'region': 'eu-west-1'});

Wir möchten jetzt eine Klasse erstellen und exportieren, die drei Methoden enthält: a get, a writeund an update.

module.exports = class DB { get(key, value, table) {} write(ID, data, table) {} async increment(ID, table) {}}

Wir beginnen mit der Erstellung unserer getMethode. Das erste , was wir tun müssen , um zu überprüfen, ob wir ein gültiges haben key,value und 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}`;

Da wir möchten, dass diese Methode auf Versprechen basiert, müssen wir a zurückgeben new Promise.

return new Promise((resolve, reject) => {})

Um Daten von Dynamo abzurufen, müssen wir eine Reihe von Parametern an den Dokumentclient übergeben. Diese Parameter müssen TableNameund enthaltenKey.

let params = { TableName: table, Key: {[key]: value}};

Wir geben diese Parameter an weiterdocumentClientund dann, rejectwenn es einen Fehler gibt oderresolvewenn nicht.

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

Ein ähnlicher Prozess wird für die writeMethode durchgeführt. Wir überprüfen, ob die Parameter gültig sind, erstellen die Parameter und übergeben sie an 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 }); });});

Die incrementMethode ist viel einfacher. Zum Inkrementieren versuchen wir, die Daten für diesen Schlüssel abzurufen, die Anzahl um eins zu erhöhen und sie dann in die Datenbank zurückzuschreiben. Wenn wir die Daten nicht erhalten können oder wenn die Daten nicht gezählt werden, gehen wir davon aus, dass wir die Anzahl auf 0 setzen müssen.

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

Ändern unseres Lambda

Jetzt haben wir eine einfache Möglichkeit, unsere Dynamo-Tabelle abzurufen, zu schreiben und zu aktualisieren. Wir können dies verwenden, damit unsere Benutzer abstimmen können. In "index.js",Wir müssen zuerst unsere neue Dynamo-Klasse importieren und eine Instanz davon erstellen.

const DB = require('./dynamo');const Dynamo = new DB();

Nun, in unserem putMovieWir können die Logik hinzufügen, damit Benutzer abstimmen können. Die beiden Dinge, die wir bekommen müssen, sind movievom Körper und genrevon den Pfadparametern. Wir kombinieren diese dann, um unsere zu erstellenmovie-genreICH WÜRDE. Dies wird dann Dynamo.incrementmit einem Tabellennamen von übergeben movie-apiund unser putMovieist vollständig.

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

Damit dies funktioniert, wenn wir das erhalten PutAnfrage müssen wir unsere Base-Handler-Funktion leicht modifizieren.

if (event.httpMethod === 'PUT') { let response = await putMovie(event) return done(response);}

Da wir unserem Lambda AWS hinzugefügt haben , müssen wir es ausführen npm initund dann npm install — save aws-sdkim Lambda-Ordner. Dies kann lokal und hochgeladen oder mit Cloud9 erfolgen.

Hinzufügen der API-Gateway-Methode

Mit der neuen Funktion können wir unserer API eine neue Methode hinzufügen. In API Gateway können wir unsere "movieAPI" auswählen und dann "/ movies / {genre}" auswählen . Klicken Sie auf „Aktionen“ -> „Create Meth o d“ und wählen Sie eine „PUT“ Methode hinzufügen.

Dieser "PUT" kann an unsere "movieAPI" gerichtet werden und "Lambda Proxy Integration verwenden" ankreuzen . Einmal gespeichert, können wir es testen. Auf der Methode können wir auf "TEST" klicken und ein Genre und einen Körper eingeben, der einen Film enthält. Wenn wir auf "TEST" klicken, erhalten wir eine Antwort mit dem Film und der neuen Anzahl. Da dies die erste Abstimmung ist, wird 1 gezählt.

Wenn Sie den Test ein zweites Mal ausführen, werden die Stimmen für diesen Film jetzt um eins erhöht.

Ändern der GET- Methode

Jetzt, da wir ein neues Abstimmungssystem haben, können wir unser "GET" aktualisieren.diese neuen Daten zu verwenden. Wir müssen alle Filme des gewünschten Genres abrufen und in der Reihenfolge ihrer Stimmen auflisten.

Wir müssen zuerst eine neue Dynamomethode erstellen. Diese Methode scannt jeden Eintrag und wählt diejenigen aus, die unseren Kriterien entsprechen.

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

Wir können jetzt unsere ändern getMoviefunction to use this new Dynamo method. We need to pass the genre, selected movie, and current count.

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 getMoviefunction so that it handles the async database scan.

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.

[ { "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.

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.

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!