0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Lambda+DynamoDB+API GatewayでRestAPI

Posted at

Lambda単体とかEC2とかECSは普通に使っていたが、試そうと思っていたが出来ていなかったサーバレス関係のメモ。
ここを主に参考にする。

ServerlesFrameworkを使えば楽なのかもしれないが、理解するためにもIaC関係は使わずに手で設定

DynamoDB

AWSのコンソール画面でDynamoDBを開いて「テーブルの作成」を選択。
テーブル名:TestTable
パーティションキー:DeviceID
ソートキー:SensorID
で、残りはデフォルトで作成。

作成したテーブルに対して項目追加でレコードを作成すると同時にvalue, unitの項目作成。
適当にテスト用レコードを作成

Lambda

LambdaからDynamoDBを操作できるようなIAMロールは必要。
AmazonDynamoDBFullAccess
AWSLambdaDynamoDBExecutionRole
をテストのためにアタッチしておいた。

PythonよりJavaScriptの方が慣れているのでnodejs(Node.js 14.x)で作成する。

DynamoをLambdaから扱う場合、AWS.DynamoDBとAWS.DynamoDB.DocumentClientがあるが、DocumentClientを使う方が楽

単純にキーで引っ掛けて検索

sample
var params = {
    TableName: "TestTable",
    Key:{
         DeviceID: "Dev0001"
    }
};
docClient.get(params, function(err, data){
    if(err){
        console.log(err);
    }else{
        console.log(data.Item);
    }
});

追加

sample
var params = {
    TableName: "TestTable",
    Item:{ // キーが必ず必要
         DeviceID: "Dev0003",
         SensorID: "Temp001",
         value: 30,
         unit: "c"
    }
};
docClient.put(params, callback);

削除

sample
var params = {
    TableName: "TestTable",
    Key:{ // キー指定
         DeviceID: "Dev0003",
    }
};
docClient.delete(params, callback);

条件を複雑にしたクエリ

sample
var params = {
    TableName: 'TestTable',
    ExpressionAttributeNames:{'#va': "value"}, // 予約語とか数値始まりは別名が必須
    KeyConditionExpression: '#va <= :val', // 条件指定
    ExpressionAttributeValues:{':val': 20} // 引数
};
// クエリの実行
docClient.query(params, function(err, data){
    if(err){
        console.log(err);
    }else{
       data.Items.forEach(function(devices, index){
           console.log(devices.DeviceID);
       });
    }
});

条件には

  • #x BETWEEN :min AND :max
  • begins_with (#x, :str)
    のようなものも存在する。

今回は単純なテストを行いたいだけなのでqueryを使った以下のようなものを作成

index.js
var AWS = require('aws-sdk');
var documentClient = new AWS.DynamoDB.DocumentClient();

var response = {
    statusCode: 200,
    headers: {},
    body: ""
  };

exports.handler =  async function(event, context) {
  // keys:[{"DeviceID":"xxx"},]
  // 内部的には複数返すようにしていない
  for (let key of event.keys) {
  
    var device_id = key.DeviceID;

    var param = {
        TableName : "TestTable",
        KeyConditionExpression: "#id = :val1",
        ExpressionAttributeNames:{ // 予約語の場合もあるので別名の割り当てが可能
            "#id": "DeviceID"
        },
        ExpressionAttributeValues: { // 引数。今回はソートキーは指定していない
            ":val1":device_id
        }
    };

    // awaitでpromiseが返ってくるのを待つ
    await documentClient.query( param, function( err, data ) {
        if (err) {
            response.statusCode = 500;
            response.body = err;
        } else {
            response.body = data;
        }
    } ).promise();

    return response;
  }
};

Lambda関数が用意できた。
LambdaにGET/PUTを渡すようにAPIGatewayで設定してやることも出来るが
メソッド単位にLambdaのスクリプトを作成するのが(処理速度も若干望めるので)一般的のようである。

API Gateway

このlambdaをCallするためのAPIGatewayを画面から設定する。
適当にDynamoTestというAPIを作成して、GETメソッドを追加。
(GETにする場合はスクリプト側のキーの取り方を変更)

  • メソッドリクエストの必須パラメータとしてクエリパラメータdevideを追加
  • 統合リクエストのapplication/jsonで以下を追加
マッピングテンプレート
{
  "keys": [{"DeviceID":"$input.params('device')"}]
}

(回りくどいやり方になってしまったが、テストになってのでよし)

テスト実行してみるとLambdaから返ってきた値が結果に表示された。
実際につかう場合はデプロイする事で反映される。
今回は自分用のテストなのでデプロイはしない。

APIキーを発行して利用を制限する事も可能

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?