1
0

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

ECS(Node.js + TypeScript)からAWS DynamoDBから最新のデータを1件のみ取得するまで

Last updated at Posted at 2020-08-31

バッチ処理をNode.js + TypeScriptで作成しており、そのバッチをECS on Fargateで起動しAWS DynamoDBから最新のデータを1件のみ取得する方法を紹介します。

その中でハマったポイントがいくつもあったため、同じ轍を踏むことがないようポイントをまとめておきます。

TL;DR

import * as AWS from 'aws-sdk';
import { DocumentClient } from 'aws-sdk/clients/dynamodb';

AWS.config.credentials = new AWS.ECSCredentials({
  httpOptions: { timeout: 5000 }, // 5 second timeout
  maxRetries: 10, // retry 10 times
});

const dynamodb = new AWS.DynamoDB();

(async () => {
  const params: DocumentClient.QueryInput = {
    TableName: "Hoge",
    KeyConditionExpression: "Code = :number",
    ExpressionAttributeValues: {
      ":number": { "N": "1111" }
    },
    ScanIndexForward: false,
    Limit: 1
  };

  const data = await dynamodb.query(params, (err, data) => {
    if (err) {
      console.log("Error", err);
    } else {
      console.log("Success", data);
    }
  }).promise();

  console.log(data.Items[0].hoge.S);
})();

ECSからDynamoDBへアクセスする方法

事前準備

事前にECSに付与するためのIAMロールを作成し、DyanamoDBへの権限を有したポリシーをアタッチしておきます。

次にECSのタスク定義、もしくはタスク実行時にタスクロールに先程作成したIAMロールを付与します。

プログラム

AWS.config.credentials = new AWS.ECSCredentials({
  httpOptions: { timeout: 5000 }, // 5 second timeout
  maxRetries: 10, // retry 10 times
});

最新の1件を取得するQuery

始めはDocumentClientを利用していましたが、どうやっても上手くいかず最終的にはDocumentClientを使わない方法に落ち着きました。

※ schemaの不一致とエラーになる

(node:1) UnhandledPromiseRejectionWarning: ValidationException: One or more parameter values were invalid: Condition parameter type does not match schema type

※未だに原因がわかっていないので、コメント頂けると嬉しいです

パラメータの型にはDocumentClient.QueryInputを指定します。

この辺はググっても全然情報が出なかったので、sdkのGitHubから引っ張ってようやくわかりましたが、どこかに載ってるのかな??🤔
https://github.com/aws/aws-sdk-js/blob/master/lib/dynamodb/document_client.d.ts

最後に最新の1件のみを取得する方法ですが、Sort Keyが設定されている状態でScanIndexForward: falseを指定すると降順でデータを取得できます。

さらにLimit: 1を指定して、1件のみ取得することが可能です。

const params: DocumentClient.QueryInput = {
  TableName: "Hoge",
  KeyConditionExpression: "Code = :number",
  ExpressionAttributeValues: {
    ":number": { "N": "1111" }
  },
  ScanIndexForward: false, // 降順(新しい順)
  Limit: 1 // 1件のみ
};

ちなみにDynamoDBのNumber型を指定しているカラムも文字列としないとエラーになりましたので、数値が与えられる場合はString型にキャストしたほうが良いみたいです。

Expected params.Item['Code'].N to be a string
ExpressionAttributeValues: {
  ":number": { "N": "1111" }
},

おわりに

今回紹介した方法は調べながらトライアンドエラーで解決まで持っていったので、もっと良い方法があるかも知れません。

見識の広い方はコメント頂けると助かります🙏

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?