4
2

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 5 years have passed since last update.

エヌシーアイ総合システムのmizu-ponです。

主に金融業務系システムの開発をしています。
AWSは勉強中ですが、知り得た知識などを載せていければと思います。

今回はLambdaからDynamoDBの操作(参照/更新)を行うまでの話です。

##Lambdaって?##
AWS

AWSが提供するサービスのひとつ。
ソースコード実行のためにサーバを立てる必要がなく色々と楽。(サーバレスアーキテクチャ)
幾つかの言語(Java,node.js(JavaScript),C#,Pythonなど)に対応している。

##DynamoDBって?##
AWS

AWSが提供するNoSQLデータベース。
NoSQLは一般的に高速かつスケールアウトに強く、IoT/ビッグデータ向きといわれている。
データをキーとバリュー(値)の組み合わせで管理する(Key-Value型)

##AWSコンソール画面##
こんな感じです。リージョン(拠点)の指定や各種サービスの呼出しができます。

AWS

##使用するテーブルの定義##
今回はIoTセンサーデータをイメージした以下のテーブルを使用します。
DynamoDBのテーブルは、主キーとデータ部からなるシンプルな構成しか許容しません。
主キーにはパーティションキー(HASH)とソートキー(RANGE)を指定できます。
NoSQLなのでSQLでのデータ操作はできず(当たり前か…)、操作コマンド(メソッド)を使ってデータ操作します。

Field Type Key
datetime String HASH
sensor_mac String RANGE
info JSON

更に、infoには以下のようなデータが含まれます。

gw_mac rssi fix battery status reserve user fix2 reserve2 timestamp exist

##開発環境(Cloud9)##
開発環境にはAWSの統合開発環境サービスであるCloud9を利用します。

Cloud9

##データの更新##
更新用のソースコードは以下のリンクからダウンロードできます。ひとつずつ解説していきます。
Markdown: JavaScript

初めの部分でrequireでライブラリ参照しています。
csvtojson:csv形式をjsonに変換
date-utils:日時のフォーマットを行う

console.log('Loading function');

const csv = require('csvtojson');
require('date-utils');

次にAWSやDynamoDBに接続するためにaws-sdkを読み込んでいます。
AWS.DynamoDB.DocumentClientはDynamoDBのレコード操作を行うクラスです。

const AWS = require("aws-sdk");

AWS.config.update({
    region: "us-west-2"
});

const docClient = new AWS.DynamoDB.DocumentClient();

exports.handlerはLambdaの関数定義の書式です。
eventには実行時の引数が入ります。

exports.handler = (event, context, callback) => {

    console.log('readdata start.');

    let sensor_data = event.payload;

今回はセンサーデータとして以下の形式のデータを指定して渡します。

{
    "payload": "$GPRP,24718902B258,FE284D4457BC,-68,02010612FF0D0082BC350100FFFFFFFF000001000000"
}

次のコードでは、引数の形式からDynamoDBに格納する形式への変換を実施しています。

    // "$GPRP" is not need
    var sensor_data_non_gprp = sensor_data.replace(/^(\$GPRP,)/g, "");

    let payload = sensor_data_non_gprp.match(/^(.{12},.{12},.*,)(.*)/);
    let split = payload[2].match(/^(02010612FF0D0082BC)(.{4})(.{2})(.{8})(.{4})(.{2})(.{6})/); 

    // split payload.
    let fix = split[1];
    let battery = split[2];
    let status = split[3];
    let reserve = split[4];
    let user = split[5];
    let fix2 = split[6];
    let reserve2 = split[7];

    // make existFlg
    var existFlg = 0;
    if (status !== "00") {
        existFlg = 1;
    }

    let now = new Date();
    var sensor_data_split_payload = payload[1]
                        + fix + "," + battery + ","
                        + status + "," + reserve + ","
                        + user + "," + fix2+ ","
                        + reserve2 + "," + now.toFormat('YYYY-MM-DD_HH24:MI:SS.') + now.getTime() + ","
                        + existFlg;

さらに次のコードでcsv形式からDynamoDBに登録するJSON形式への変換を実施しています。

    csv({
        noheader: true,
        headers: [
            'sensor_mac',
            'gw_mac',
            'rssi',
            'fix',
            'battery',
            'status',
            'reserve',
            'user',
            'fix2',
            'reserve2',
            'timestamp',
            'exist'],
        colParser:{
            "exist":"number"
        }
    }).fromString(sensor_data_split_payload)
        .on('json',(jsonObj)=>{

        // Insert DynamoDB
        var params = {
            TableName:table,
            Item:{
                "datetime": jsonObj.timestamp,
                "sensor_mac": jsonObj.sensor_mac,
                "info":{
                    "gw_mac": jsonObj.gw_mac,
                    "rssi": jsonObj.rssi,
                    "fix": jsonObj.fix,
                    "battery": jsonObj.battery,
                    "status": jsonObj.status,
                    "reserve": jsonObj.reserve,
                    "user": jsonObj.user,
                    "fix2": jsonObj.fix2,
                    "reserve2": jsonObj.reserve2,
                    "timestamp": jsonObj.timestamp,
                    "exist": jsonObj.exist
                }
            }
        };

docClient.putメソッドで先ほど作成したparamsをDynamoDBへレコード挿入します。

        console.log("Adding a new item...");
        docClient.put(params, function(err, data) {

            if (err) {
                console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
            } else {
                console.log("Added item:", JSON.stringify(data, null, 2));
            }
        });

[コードの実行]

Cloud9上で、"Run"を押下することでコードの実行ができます。

Cloud9Exec

##データの参照##
検索用のソースコードは以下のリンクからダウンロードできます。
Markdown: JavaScript

引数に検索キーを指定し、docClient.scanメソッドで範囲検索します。

    var params = {
        TableName: table,
        FilterExpression: "#sm = :key1 AND begins_with(#dt, :key2)",
        ExpressionAttributeNames: {
            "#sm": "sensor_mac",
            "#dt": "datetime"
        },
        ExpressionAttributeValues: {
            ":key1": event.key1,
            ":key2": event.key2,
        }
    };

    console.log("Scanning Sensordata table.");
    docClient.scan(params, onScan);

[コードの実行]
Cloud9上の実行結果

Cloud9Exec

##Lambda関数のデプロイ##
Cloud9の左側に"AWS Resources"というメニューがあり、ここからデプロイします。

Cloud9Deploy

デプロイされると、AWS上にLambda関数として登録され、他から呼出すことが可能です。

Cloud9Deploy

以上、終わりです。

4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?