Πώς να ενσωματώσετε το DynamoDB στο API σας χρησιμοποιώντας το AWS Lambda

Στο πρώτο μέρος αυτού του σεμιναρίου, δημιουργήσαμε ένα API που μεταβίβασε αιτήματα σε μια Lambda που επέστρεψε την κορυφαία τηλεοπτική εκπομπή ή ταινία για αυτό το είδος. Τώρα πρόκειται να χρησιμοποιήσουμε το DynamoDB για να επιτρέψουμε στους χρήστες να ψηφίσουν το αγαπημένο τους είδος.

Αν δεν έχετε διαβάσει το πρώτο μέρος αυτής της σειράς, ρίξτε μια ματιά εδώ!

DynamoDB

Το DynamoDB είναι μια μη σχετική βάση δεδομένων που δημιουργήθηκε από την Amazon την οποία μπορούμε να χρησιμοποιήσουμε για να αποθηκεύσουμε τις ψήφους των χρηστών. Είναι επίσης υπέροχο, γιατί μπορούμε εύκολα να το έχουμε πρόσβαση χρησιμοποιώντας το aws-sdkπου έχει προεγκαταστήσει η Lambdas.

Το πρώτο πράγμα που πρέπει να κάνουμε είναι να δημιουργήσουμε έναν πίνακα για την αποθήκευση των ψήφων της ταινίας. Μεταβείτε στο DynamoDB στο AWS και κάντε κλικ στο "Δημιουργία πίνακα".

Στην επόμενη σελίδα, θα ονομάσουμε τον πίνακα μας και θα παρέχουμε ένα πρωτεύον κλειδί. Το πρωτεύον κλειδί πρέπει να είναι μοναδικό, έτσι δεν έχουμε δύο εγγραφές με το ίδιο κλειδί. Μπορούμε να καλέσουμε τον πίνακα "movie-api" και να ορίσουμε το κύριο κλειδί σε "movie-genre", καθώς κάθε ταινία θα πρέπει να εμφανίζεται μόνο μία φορά σε κάθε είδος.

Τώρα έχουμε ρυθμίσει όλα όσα πρέπει να ρυθμίσουμε στο DynamoDB ώστε να μπορέσουμε να επιστρέψουμε στον κώδικά μας.

Προσθήκη ενός χειριστή Dynamo

Η λήψη και η τοποθέτηση δεδομένων σε έναν πίνακα Dynamo γίνεται χρησιμοποιώντας το documentClienton aws-sdk , αλλά η δομή των αιτημάτων είναι πολύ συγκεκριμένη. Για να κάνουμε τη ζωή μας ευκολότερη, μπορούμε να κάνουμε έναν χειριστή Dynamo να κάνει όλη τη μορφοποίηση.

Ξεκινήστε δημιουργώντας ένα νέο αρχείο με το όνομα "dynamo.js" στο "movieAPI" Lambda. Σε αυτό το αρχείο ξεκινάμε απαιτώντας aws-sdk και δημιουργώντας το δικό μας documentClient.

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

Θέλουμε τώρα να δημιουργήσουμε και να εξαγάγουμε μια κλάση που έχει τρεις μεθόδους σε αυτήν: a get, a write, and an update.

module.exports = class DB { get(key, value, table) {} write(ID, data, table) {} async increment(ID, 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}`;

Επειδή θέλουμε αυτή τη μέθοδο να βασίζεται σε υποσχέσεις, πρέπει να επιστρέψουμε ένα new Promise.

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

Για να λάβουμε δεδομένα από το Dynamo, πρέπει να περάσουμε ένα σύνολο παραμέτρων στον πελάτη εγγράφων. Αυτά τα params πρέπει να περιλαμβάνουν TableNameκαιKey.

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

Περνάμε αυτές τις παραμέτρους στο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);});

Μια παρόμοια διαδικασία γίνεται για τη 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 }); });});

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

Τροποποίηση της λάμδα μας

Τώρα έχουμε έναν εύκολο τρόπο λήψης, γραφής και ενημέρωσης του πίνακα Dynamo. Μπορούμε να το χρησιμοποιήσουμε για να επιτρέψουμε στους χρήστες μας να ψηφίσουν. Μέσα στο "index.js",Πρέπει πρώτα να εισαγάγουμε τη νέα κλάση Dynamo και να δημιουργήσουμε μια παρουσία της.

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

Τώρα, μέσα μας putMovieμπορούμε να προσθέσουμε τη λογική για να επιτρέψουμε στους χρήστες να ψηφίζουν. Τα δύο πράγματα που πρέπει να πάρουμε είναι movieαπό το σώμα και genreαπό τις παραμέτρους της διαδρομής. Στη συνέχεια τα συνδυάζουμε για να δημιουργήσουμε το δικό μαςmovie-genreΤΑΥΤΟΤΗΤΑ. Αυτό στη συνέχεια μεταφέρεται Dynamo.incrementμε ένα όνομα πίνακα movie-apiκαι το δικό μας 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')}

Για να λειτουργήσει αυτό όταν λάβουμε το Putαίτημα, πρέπει να τροποποιήσουμε ελαφρώς τη λειτουργία χειριστή βάσης.

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

Επειδή έχουμε προσθέσει AWS στο Lambda μας, πρέπει να τρέξουμε npm initκαι στη συνέχεια, npm install — save aws-sdkενώ στο φάκελο Lambda. Αυτό μπορεί να γίνει τοπικά και να μεταφορτωθεί ή να γίνει χρησιμοποιώντας το Cloud9.

Προσθήκη της μεθόδου API Gateway

Με τη νέα λειτουργία, μπορούμε να προσθέσουμε μια νέα μέθοδο στο API μας. Στο API Gateway, μπορούμε να επιλέξουμε το "movieAPI" και στη συνέχεια να επιλέξουμε "/ movies / {genre}" . Κάντε κλικ στο «Ενέργειες» -> «Δημιουργία Meth o d» και να επιλέξετε να προσθέσετε μια μέθοδο «PUT».

Αυτό το «put» μπορεί να απευθύνεται σε μας «movieAPI» , και επιλέξτε «Χρήση Lambda μεσολάβησης Ένταξη». Μόλις αποθηκευτεί μπορούμε να το δοκιμάσουμε. Στη μέθοδο μπορούμε να κάνουμε κλικ στο "TEST" και να εισαγάγουμε ένα είδος και ένα σώμα που περιέχει μια ταινία. Όταν κάνουμε κλικ στο "ΔΟΚΙΜΗ" λαμβάνουμε μια απάντηση που περιέχει την ταινία και το νέο πλήθος. Δεδομένου ότι αυτή είναι η πρώτη ψηφοφορία, η μέτρηση θα είναι 1.

Η εκτέλεση της δοκιμής για δεύτερη φορά θα αυξήσει τώρα τις ψήφους για αυτήν την ταινία κατά μία.

Τροποποίηση της μεθόδου GET

Τώρα που έχουμε ένα νέο σύστημα ψηφοφορίας, μπορούμε να ενημερώσουμε το "GET"για να χρησιμοποιήσετε αυτά τα νέα δεδομένα. Πρέπει να πάρουμε όλες τις ταινίες που είναι στο είδος που ζητήθηκε και να τις παραθέσουμε με σειρά ψήφων.

Πρέπει πρώτα να φτιάξουμε μια νέα μέθοδο δυναμό. Αυτή η μέθοδος θα σαρώσει κάθε μία από τις καταχωρίσεις και θα διαλέξει αυτές που πληρούν τα κριτήριά μας.

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

Μπορούμε τώρα να τροποποιήσουμε το δικό μας 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.

Εάν σας άρεσε αυτό, φροντίστε να το κάνετε χειροκρότημα και να εγγραφείτε για περισσότερα μαθήματα και οδηγούς Amazon. Τα λέμε στο επόμενο άρθρο και συνεχίστε την κωδικοποίηση!