lambda入門(Node)② - lambdaからdynamoDBへデータを保存する

前回は、lambdaを実際に動かす環境をserverless flameworkを使って整えました
[こちらから](http://qiita.com/smith_30/items/ae32c3596b86c49d40c2)見れますのでよろしければ

## 今回やること

lambdaとdynamoDBの連携

## そもそもdynamoDBってどうやって使うの

知っていた特徴としては、NoSQLのDBということぐらい。。

なので、使いながら学んだことをメモっておくとします。

### dynamoDBで気になったこと

- プロビジョニングされたスループットの容量と使用したストレージ分で請求が行われる
`プロビジョニングされたスループットの容量`
調べた感じ、秒あたりの(読み込み or 書き込み)で行われるデータの容量のこと。
これは、インデックスをつけたりで変わってくるようだ
これはテーブルを作るときに設定する。

- 自動的に3箇所の施設にデータのバックアップが行われる
どれか１つが落ちて、itemの整合性が取れない場合は、他のと比較して
正しい値を返却してくれるようになっているらしい
読み取りコストはその分増大する

- dynamoDBからテーブルと呼ばれるものを定義して、そこにデータを格納する
概念的にはMySQLでいうテーブルと同じ理解で大丈夫そう

- テーブルにはitemと呼ばれるものが保存される
これは、MySQLでいうレコードのようなもの

- 各アイテムは一意のプライマリーキーも持っている

- itemは、attiributeをもつ
これは、MySQLでいえば、カラムのこと
ただ、dynamoDBはNoSQLなので、同じテーブル内のitemが同一のattributeを持つ必要がない


## serverless flameworkにdynamoDBの設定をしていく

```yaml:serverless.yml
provider:
  name: aws
  runtime: nodejs4.3
  stage: ${opt:stage} # production stage is [prod], pass by '--stage [value]' option
  region: ap-northeast-1
  iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:DescribeTable
          - dynamodb:Query
          - dynamodb:Scan
          - dynamodb:GetItem
          - dynamodb:PutItem
          - dynamodb:UpdateItem
          - dynamodb:DeleteItem
        Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.stage}-*"
  # environmentの値は、lambda function内で
  # process.env.{key}でアクセスする
  environment:
    stage: ${self:provider.stage}
    bookTable: ${self:provider.stage}-books

resources:
  Resources:
    BookDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        AttributeDefinitions:
          -
            AttributeName: id
            AttributeType: "S"
        KeySchema:
          -
            AttributeName: id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: ${self:provider.environment.bookTable}
```

この設定をデプロイすると、dynamoDBに{env}-booksのテーブルが作られる

```bash
$ serverless deploy -v --stage dev
```

## lambdaからdynamoDBに書き込む

uuidを追加しました。

```bash
$ npm install uuid
```

lambda スクリプト

```js:store.js
'use strict';

const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB();
const documentClient = new AWS.DynamoDB.DocumentClient();
const bookTable = process.env.bookTable;

//Generate and return a RFC4122 v1 (timestamp-based) UUID.
const uuidV1 = require('uuid/v1');

//Generate and return a RFC4122 v4 (random) UUID.
// const uuidV4 = require('uuid/v4');

module.exports.store = (event, context, callback) => {
  
　//書き込み
  documentClient.put( {
    'TableName': bookTable,
    "Item": {
      "id": uuidV1(),
      "title": "hello"
    }
  }, function(err, data) {
    console.log(err);
  });

　//読み込み
  dynamo.scan({
    'TableName': bookTable
  }, function(err, data){
    console.log(JSON.stringify(data));
  });
  
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'ok',
      input: event,
    }),
  };

  callback(null, response);
};
```

```yml:serverless.yml
functions:
  bookStore:
    handler: books/store.store
```

```bash
$ serverless invoke --stage dev -f bookStore -l
```

## 開発の効率化のために

functionのみのデプロイはこのようにもできる

```bash
# 指定ファンクションのみ更新
$ serverless deploy function -f [functionName]
```

## 次回

apiとして使えるようにCRUDの実装をしていこうかと思います。
ApiGateWayとか触ってみよう。