Как интегрировать DynamoDB в свой API с помощью AWS Lambda

1656573492 kak integrirovat dynamodb v svoj api s pomoshhyu aws lambda

автор Сэм Уильямс

NRiku0VLpjCZJtuf14-rhKFtFpHe2iqs9oZP

В первой части этого руководства мы создали API, который передавал запросы Lambda, который возвращал лучшее телешоу или фильм для этого жанра. Теперь мы собираемся использовать DynamoDB, чтобы разрешить пользователям голосовать за свой любимый жанр.

Если вы не читали первую часть этой серии, посмотрите ее здесь!

DynamoDB

DynamoDB – это нереляционная база данных, созданная Amazon, которую мы можем использовать для хранения голосов пользователей. Это также замечательно, поскольку мы можем легко получить к нему доступ с помощью aws-sdk которые лямбда предварительно установлена.

Первое, что нам нужно сделать это создать таблицу для хранения голосов за фильм. Выделите DynamoDB в AWS и нажмите кнопку «Создать таблицу».

gw6O3QWWUiAy784JH5lWIm1K2SVgfq7dNFT9
HyNfOnvaam0CEq7vhE-YBZZ9lWcdHDBtJEZT

На следующей странице мы дадим название таблицы и предоставим первичный ключ. Первичный ключ должен быть уникален, чтобы у нас не было двух записей с одинаковым ключом. Мы можем назвать таблицу movie-api и установить первичный ключ на movie-genre, поскольку каждый фильм должен появляться только один раз в каждом жанре.

Теперь мы настроили все, что нам нужно настроить в DynamoDB, чтобы мы могли вернуться в наш код.

Добавление обработчика Dynamo

Получение и размещение данных в таблице Dynamo осуществляется с помощью documentClient на 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а writeи 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}`;

Поскольку мы хотим, чтобы этот метод был основан на обещаниях, нам нужно вернуть a new Promise.

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

Для получения данных от Dynamo нам нужно передать набор параметров клиенту документов. Эти параметры необходимо включать 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 });    });});

The 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 ID. Это потом передается 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 к нашей лямбде, нам нужно бежать npm init и затем npm install — save aws-sdk находясь в папке Lambda. Это можно сделать локально и загрузить или сделать с помощью Cloud9.

Добавление метода API Gateway

С помощью новой функции мы можем добавить новый метод в наш API. В API Gateway мы можем выбрать наш movieAPI, а затем выбрать /movies/{genre}. Нажмите «Действия» -> «Создать Methоd» и выберите добавить метод «PUT».

nkKXDo9fZIwCBmib5CuBVhOuPYgt5kCxuF7b

Этот PUT можно направить на наш movieAPI, и поставьте галочку «Использовать интеграцию Lambda Proxy». После сохранения мы можем протестовать его. В методе мы можем нажать TEST и ввести жанр и тело, содержащее фильм. Когда мы нажимаем TEST, мы получаем ответ, содержащий фильм и новый счет. Поскольку это первый голос, подсчет будет 1.

22fOgFeE-f4fu84NrhXqW3NDtfYjCpiDfMCO
Z6vdhExeuNJFJQCoAZZcHdndLzjRy3hmxu0I
mLrC1ijul84nx3VvTJsjo6RFIZCjQqHIHQ7e

Запуск теста второй раз приведет к увеличению голосов за этот фильм на один.

ZriL39b1A9v2MyEFt4Zlk7oat5jHGVrT6DZj

Изменение ПОЛУЧИТЬ метод

Теперь, когда у нас есть новая система голосования, мы можем обновить нашу «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);         });    });}

Теперь мы можем изменить нашу 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;}

Последнее, что нужно сделать, это добавить await перед выходом getMovie функция, чтобы она обрабатывала асинхронное сканирование базы данных.

let response = await getMovie(event);

Тестирование

Когда мы попадаем на эту новую конечную точку GET, мы получаем упорядоченный список всех фильмов в базе данных.

[  {    "count": 2,    "ID": "Desperado (1995)-action",    "genre": "action"  },  {    "count": 1,    "ID": "Team America (2004)-action",    "genre": "action"  }]

Резюме

Теперь мы создали API, который может обрабатывать запросы GET и PUT, сохраняя и получая данные из базы данных Dynamo. Вы также можете повторно использовать много кода класса Dynamo для других API, работающих с Dynamo.

Хотите попрактиковаться?

Если вам это понравилось, почему бы не попытаться реализовать подобные настройки для телевизионных шоу? Если да, то дайте мне знать, как все идет!

Вы также можете улучшить этот API, убедившись в этом Desperado (1995) и desperado (1995) оба учитываются в один фильм или допускают только определенный формат названия фильма.

Если вам это понравилось, не забудьте похлопать и подписаться на дополнительные пособия и пособия Amazon. До встречи в следующей статье и продолжайте кодировать!

SClwEaQxE4CUJ6oJviWTugWNaGOAH4Xxqohh

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *