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

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

```javascript

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

};

```

フロント側

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

}
 
```