Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Organize your chaotic DynamoDB (with Node.js) /...

Organize your chaotic DynamoDB (with Node.js) / Organize your chaotic DynamoDB with Nodejs

osamu.arita

May 11, 2021
Tweet

More Decks by osamu.arita

Other Decks in Programming

Transcript

  1. ABOUT ME
 • LINE Fukuokaのエンジニア
 ◦ 以前はiOSエンジニアをしていました
 ◦ 今は「LINE SMART

    CITY GovTech プログラム」の開発サポート全般
 • 社会人歴15年 / 社歴1年目
 ◦ AWS / Firebase / Ruby on Rails / PHP(Laravel、etc..) 
 ◦ iOS(swift)/ Android(Kotlin / Java)/ Flutter(Dart) 
 • GWは、息子(現5歳)と遊ぶのが中心でした
 • slack - #z_osamu
 
 osamu_arita
 osamu.arita

  2. RDBMSとNoSQLの比較
 
 RDBMS(RDS)
 NoSQL(DynamoDB) 
 スキーマ (テーブル定義)
 スキーマあり
 プライマリーキー以外はスキーマレス 


    拡張性
 -
 高
 トランザクション
 ACID特性
 ・原子性 (Atomicity)
 ・一貫性 (Consistency)
 ・独立性 (Isolation)
 ・永続性 (Durability)
 BASE特性
 ・基本的に利用可能 (Basically Available) 
 ・厳密ではない状態遷移 (Soft state) 
 ・結果整合性 (Eventual consistency) 
 
 【備考】
 ・ConsistentRead(強い整合性のある読み込み)パラメータ あり
 ・DynamoDB Transactions API:リージョン内でACIDを保 証
 操作
 SQL
 ・Classic API
 ・PartiQL(パーティクル) - SQL互換の クエリ言語 

  3. DynamoDBのテーブル要素
 Partition Key
 Sort Key
 Attribute
 Item
 Attribute
 Attribute
 Attribute


    Schema定義
 他に Secondary Index もあります 
 LSI - Sort Key以外で絞り込み。テーブル作成時に定義 
 GSI - Partition Keyを別途設定。後で追加可能。但しコスト大 

  4. とあるプロジェクトの構成
 エンジニアAさん
 リポジトリ
 エンジニアBさん
 GitHub
 commit & push
 commit &

    push
 deploy (AWS CloudFormation, AWS SAM) 
 
 pull
 pull
 AWS(Serverless構成)
 DynamoDB
 AWS Lambda 
 API Gawatey
 Node.js
 table A
 table B
 ※フロントエンドなど細かい部分は省略 

  5. とあるプロジェクトの構成
 エンジニアAさん
 リポジトリ
 エンジニアBさん
 GitHub
 commit & push
 commit &

    push
 deploy (AWS CloudFormation, AWS SAM) 
 
 pull
 pull
 AWS(Serverless構成)
 DynamoDB
 AWS Lambda 
 API Gawatey
 Node.js
 table A
 table B
 ※フロントエンドなど細かい部分は省略 
 ファイルA:table A に「updateAt」追加 
 ファイルB:table A に「memo」追加 

  6. とあるプロジェクトの構成
 エンジニアAさん
 リポジトリ
 エンジニアBさん
 GitHub
 commit & push
 commit &

    push
 deploy (AWS CloudFormation, AWS SAM) 
 
 pull
 pull
 AWS(Serverless構成)
 DynamoDB
 AWS Lambda 
 API Gawatey
 Node.js
 table A
 table B
 ※フロントエンドなど細かい部分は省略 
 エンジニアCさん参加

  7. とあるプロジェクトの構成
 エンジニアAさん
 リポジトリ
 エンジニアBさん
 GitHub
 commit & push
 commit &

    push
 deploy (AWS CloudFormation, AWS SAM) 
 
 pull
 pull
 AWS(Serverless構成)
 DynamoDB
 AWS Lambda 
 API Gawatey
 Node.js
 table A
 table B
 ※フロントエンドなど細かい部分は省略 
 エンジニアCさん
 tableの構成がソースコード上でバラついて
 全然わからない!

  8. DynamoDB操作 - Node.JS
 • AWS SDK for JavaScriptで提供されているライブラリ 
 ◦

    v2
 
 
 
 ◦ v3
 
 
 ◦ 参考
 ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/dynamodb-example-document-client.html
 ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/welcome.html
 const {DynamoDB} = require("@aws-sdk/client-dynamodb" ); const { DynamoDBClient, ListTablesCommand }= require('@aws-sdk/client-dynamodb' ); // Commandベースでテーブル一覧取得やテーブル操作など const dbclient = new DynamoDBClient({ region: 'us-west-2' }); var AWS = require('aws-sdk'); AWS.config.update( {region: 'REGION'}); // テーブル一覧取得など var ddb = new AWS.DynamoDB({apiVersion: "2006-03-01" }); // テーブル操作 var docClient = new AWS.DynamoDB. DocumentClient({apiVersion: '2012-08-10' });
  9. DynamoDB操作 - Node.JS
 • AWS SDK for JavaScriptで提供されているライブラリ 
 ◦

    v2
 
 
 
 ◦ v3
 
 
 ◦ 参考
 ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/dynamodb-example-document-client.html
 ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/welcome.html
 const {DynamoDB} = require("@aws-sdk/client-dynamodb" ); const { DynamoDBClient, ListTablesCommand }= require('@aws-sdk/client-dynamodb' ); // Commandベースでテーブル一覧取得やテーブル操作など const dbclient = new DynamoDBClient({ region: 'us-west-2' }); var AWS = require('aws-sdk'); AWS.config.update( {region: 'REGION'}); // テーブル一覧取得など var ddb = new AWS.DynamoDB({apiVersion: "2006-03-01" }); // テーブル操作 var docClient = new AWS.DynamoDB. DocumentClient({apiVersion: '2012-08-10' }); v3のメリット
 ・SDKがTypeScriptで記述されている 
 ・サービスごとに個別のパッケージが利用可能 
 ・新しいmiddlewareStack 
 など
 

  10. DynamoDB Table定義集約 - Node.JS
 • Amazon DynamoDB DataMapper For JavaScript

    
 ◦ awslabsが提供しているライブラリ 
 ◦ modelを作成することでTable定義を集約できる 
 
 
 
 
 
 ◦ 参考
 ▪ https://github.com/awslabs/dynamodb-data-mapper-js
 ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/
 
 @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; }
  11. DynamoDB Table定義集約 - Node.JS
 • Amazon DynamoDB DataMapper For JavaScript

    
 ◦ awslabsが提供しているライブラリ 
 ◦ modelを作成することでTable定義を集約できる 
 
 
 
 
 
 ◦ 参考
 ▪ https://github.com/awslabs/dynamodb-data-mapper-js
 ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/
 
 @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; } コードとしてはv2に対応 

  12. DynamoDB Table定義集約 - Node.JS
 • Amazon DynamoDB DataMapper For JavaScript

    
 ◦ awslabsが提供しているライブラリ 
 ◦ modelを作成することでTable定義を集約できる 
 
 
 
 
 
 ◦ 参考
 ▪ https://github.com/awslabs/dynamodb-data-mapper-js
 ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/
 
 @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; } dynamodb-data-mapper-annotations を利用すると
 左記のようにきれいに書けるけれど、 
 JavaScriptで記載する場合は以下の通り 
 
 class MyDomainObject {
 }
 
 Object.defineProperties(MyDomainObject.prototype, {
 [DynamoDbTable]: {
 value: 'table_name'
 },
 [DynamoDbSchema]: {
 value: {
 id: {
 type: 'String',
 keyType: 'HASH'
 },
 foo: {
 type: 'String',
 keyType: 'RANGE'
 },
 :
 },
 },
 });

  13. DynamoDB Table定義集約 - Node.JS
 • Amazon DynamoDB DataMapper For JavaScript

    
 ◦ awslabsが提供しているライブラリ 
 ◦ modelを作成することでTable定義を集約できる 
 
 
 
 
 
 ◦ 参考
 ▪ https://github.com/awslabs/dynamodb-data-mapper-js
 ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/
 
 @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; } dynamodb-data-mapper-annotationsを利用する場合 
 
 tsconfig.jsonで experimentalDecorators と emitDecoratorMetadata オプションを true にする必要あり
 
 tsconfig.json
 {
 "compilerOptions": {
 "experimentalDecorators ": true,
 "emitDecoratorMetadata ": true,
 }
 

  14. DocumentClient(v2)とDataMapperの比較 (1)
 
 DocumentClient(v2) 
 DataMapper
 scan
 scan(params, callback) ⇒

    AWS.Request 
 scan<T extends StringToAnyObjectMap>( 
 valueConstructor: ZeroArgumentsConstructor<T>, 
 options?: ScanOptions|ParallelScanWorkerOptions 
 ): ScanIterator<T>;
 get
 get(params, callback) ⇒ AWS.Request 
 get<T extends StringToAnyObjectMap = StringToAnyObjectMap>( 
 item: T,
 options?: GetOptions 
 ): Promise<T>;
 put
 put(params, callback) ⇒ AWS.Request 
 put<T extends StringToAnyObjectMap = StringToAnyObjectMap>( 
 item: T,
 options?: PutOptions 
 ): Promise<T>;
 一通りのメソッドは用意されている。scanは戻り値の型がPromiseではないので注意 

  15. DocumentClient(v2)とDataMapperの比較 (2)
 
 DocumentClient(v2) 
 DataMapper
 update
 update(params, callback) ⇒

    AWS.Request
 update<T extends StringToAnyObjectMap = StringToAnyObjectMap>( 
 item: T,
 options?: UpdateOptions 
 ): Promise<T>;
 delete
 delete(params, callback) ⇒ AWS.Request
 delete<T extends StringToAnyObjectMap = StringToAnyObjectMap>( 
 item: T,
 options?: DeleteOptions 
 ): Promise<T|undefined>;
 • 参考
 ◦ https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html
 ◦ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/
 ◦ https://github.com/awslabs/dynamodb-data-mapper-js/blob/master/packages/dynamodb-data-mapper/src/DataMapper.ts
 一通りのメソッドは用意されている 

  16. 試してみた構成
 エンジニアAさん
 ・言語:TypeScript(※1) 
 ・DynamoDB:create-table / put-item 
 ・AWS Lambda:create-function

    / delete-function / invoke 
 (※1)dynamodb-data-mapperのサンプルがTypeScriptベース 
 localstack
 DynamoDB
 AWS Lambda 
 Node.js
 テーブル:
 SurveyResults 
 
 • 参考
 ◦ https://github.com/localstack/localstack
 ◦ https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/workbench.settingup.html
 ・AWS提供のNoSQL Workbenchで実際のデータ確認 

  17. 試してみた構成
 エンジニアAさん
 ・言語:TypeScript(※1) 
 ・DynamoDB:create-table / put-item 
 ・AWS Lambda:create-function

    / delete-function / invoke 
 (※1)dynamodb-data-mapperのサンプルがTypeScriptベース 
 localstack
 DynamoDB
 AWS Lambda 
 Node.js
 テーブル:
 SurveyResults 
 
 • 参考
 ◦ https://github.com/localstack/localstack
 ◦ https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/workbench.settingup.html
 ・AWS提供のNoSQL Workbenchで実際のデータ確認 
 ・サービス共通で http://localhost:4566/ にてアクセス可能
 ・localstack内でアクセスする場合、 http://${process.env.LOCALSTACK_HOSTNAME}:4566 
 とLOCALSTACK_HOSTNAMEを利用することでアクセス可能 

  18. とあるプロジェクトの構成
 エンジニアAさん
 リポジトリ
 エンジニアBさん
 GitHub
 commit & push
 commit &

    push
 deploy (AWS CloudFormation, AWS SAM) 
 
 pull
 pull
 AWS(Serverless構成)
 DynamoDB
 AWS Lambda 
 API Gawatey
 Node.js
 table A
 table B
 ※フロントエンドなど細かい部分は省略 
 エンジニアCさん
 tableの構成がソースコード上でバラついて
 全然わからない!

  19. とあるプロジェクトの構成
 エンジニアAさん
 リポジトリ
 エンジニアBさん
 GitHub
 commit & push
 commit &

    push
 deploy (AWS CloudFormation, AWS SAM) 
 
 pull
 pull
 AWS(Serverless構成)
 DynamoDB
 AWS Lambda 
 API Gawatey
 Node.js
 table A
 table B
 ※フロントエンドなど細かい部分は省略 
 エンジニアCさん
 tableの構成がソースコード上で
 わかる(わかりそう)!

  20. まとめ
 • カオスなDynamoDB
 ◦ 複数のエンジニアが開発を行い、table情報がソースコード上でばらついている状態 
 • DataMapperを利用する事で、モデルとして整理できそう
 ◦ ただし・・


    ▪ scanの戻り値の型がScanIteratorでPromiseと異なるので注意 
 ▪ AWS SDK for JavaScript (v3) を利用したい場合は、別の方法を検討 
 • DynamoDBを試したい場合、localstack+NoSQL Workbenchは便利!