LoginSignup
2
2

More than 5 years have passed since last update.

AWS API Gateway + Lambdaを使ってDynamoDBからデータを取得してチャートに表示する

Last updated at Posted at 2018-09-18

user_idで絞って、タイムスタンプとポイントのチャートを表示するサンプルです。

SDKとチャートはコレを使いました
http://www.chartjs.org/
https://sdk.amazonaws.com/js/aws-sdk-2.315.0.min.js

エラー処理とかは適当です。

AWS API Gateway + Lambda側

DynamoDBからデータ抽出して返すLambda


const aws = require("aws-sdk")
const docClient = new aws.DynamoDB.DocumentClient({
  region: "ap-northeast-1",
  accessKeyId: process.env.ACCESS_KEY_ID,
  secretAccessKey: process.env.SECRET_ACCESS_KEY
})

exports.handler = async (event) => {
  const user_id = event.user_id;

  //
  // metaデータを取得
  //
  var params1 = {
    TableName: "metatable",
    FilterExpression: "#user_id = :user_id",
    ExpressionAttributeNames: {
        "#user_id": "user_id"
    },
    ExpressionAttributeValues: {
        ":user_id": user_id
    }
  };
  // const data = await docClient
  const data_meta = await docClient
    .scan(params1)
    .promise()
    .catch(err => {
      console.error(err)
      return { Items: [] }
    })

  //
  // ポイントの推移を取得
  //
  var params = {
      TableName: "pointtable",
      FilterExpression: "#user_id = :user_id",
      ExpressionAttributeNames: {
          "#user_id": "user_id"
      },
      ExpressionAttributeValues: {
          ":user_id": user_id
      }
  };

  const data = await docClient
    .scan(params)
    .promise()
    .catch(err => {
      console.error(err)
      return { Items: [] }
    })

  // 日付でサマリして表示するため、timestamptを日付に変換しておく
  var points = [];
  for (let item of data.Items) {
    var dt = new Date(item.timestamp * 1000);
    var y = dt.getFullYear();
    var m = ('0' + (dt.getMonth() + 1)).slice(-2);
    var d = ('0' + (dt.getDate())).slice(-2);
    dt = y + "/" + m + "/" + d;

    points.push({
      "date" : dt,
      "point" : item.point
    });

  }

  // 日付で集計
  var sum = {};
  points.forEach(o => sum[o.date] = (sum[o.date] || 0) + o.point);
  var res = Object.keys(sum).sort((a, b) => a > b ? 1 : -1).map(date => ({date, point: sum[date]}));

  return {
    body: {
      // "points": data.Items.sort((x, y) => x.timestamp > y.timestamp),
      "points": res,
      "meta" : data_meta.Items
    }
  }

};

フロント側

window.onload = function (e) {
    liff.init(function (data) {
        initialize(data.context.userId, data_summary);
    });

};

function draw_chart(labels,pointData) 
{
    var ctx = document.getElementById("point_chart");
    var c = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: labels,
        datasets: [{
                label: 'ポイント',
                data: pointData,
                borderColor: '#53B535',
                backgroundColor: '#53B535',
                fill: false,
                pointRadius: 5,
                pointHoverRadius: 5
            }]
        }
    });
}

function initialize(user_id, callback) {
    const res = new XMLHttpRequest();
    res.open("GET", 'https://XXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod?user_id=' + user_id);
    res.addEventListener("load", (event) => {
        callback(event);
    });
    res.addEventListener("error", () => {
        console.error("error");
    });
    res.send();
}

function data_summary(event){
    // console.log(event);

    if (event.target.status !== 200) {
        console.log(`${event.target.status}: ${event.target.statusText}`);
        return;
    }
    var response = JSON.parse(event.target.responseText);
    if (! response.body) {
        console.log('response body is null');
        return;
    }

    var data = response.body;
    // console.log(data.points);


    // 日付でサマリ
    var labels = [];
    var point_data = [];
    var point = 0;
    for (var i=0; i < data.points.length; i++) {
        // ラベル
        labels.push(data.points[i].date);

        // ポイント(推移を表すため足す)
        point = point + data.points[i].point;
        point_data.push(point);
    }

    console.log(labels);
    console.log(point_data);
    if (!labels || ! point_data){
        return;
    }


    // チャートに表示する直近の日数
    var _point_data = [];
    const SHOW_DAY = 7;
    if (labels.length > SHOW_DAY){
        var start_index = labels.length - SHOW_DAY;
        labels = labels.slice(start_index);
        // console.log(start_index);
        for (var i= start_index; i < point_data.length; i++) {
            _point_data.push(point_data[i]); 
        }

        console.log(labels);
        console.log(_point_data);
    }else{
        _point_data = point_data;
    }
    draw_chart(labels,_point_data);

    // 合計ポイント
    if (data.meta[0]){
        document.getElementById("point_total").innerText = (data.meta[0].points || 0);
    }

}

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