前回は、サーバーレスオフラインで DynamoDB にデータを保存しました。

今回は、DynamoDB に保存したデータを取得します。

まずは、データを取得するためにハンドラーを作成します。

api フォルダに、get-notes.js を作成します。

前回作成した、create-note.js の内容を流用します。

const AWS = require("aws-sdk")
AWS.config.update({ region: "us-west-2" })

const dynamodb = new AWS.DynamoDB.DocumentClient()
const tableName = process.env.NOTES_TABLE

exports.handler = async event => {
  try {
    return {
      statudCode: 200,
      headers: { "Access-Control-Allow-Origin": "*" },
      body: JSON.stringify(item),
    }
  } catch (err) {
    console.log("Error:", err)
    return {
      statusCode: err.statusCode ? err.statusCode : 500,
      headers: { "Access-Control-Allow-Origin": "*" },
      body: JSON.stringify({
        error: err.name ? err.name : "Exception",
        message: err.message ? err.message : "Unknown error",
      }),
    }
  }
}

まずは、eventquieryStringParametersで、パラメータを取得できるようにします。

exports.handler = async (event) => {
  try {
    let query = event.queryStringParameters;

一度に取得するデータを最大 10 件にします。

exports.handler = async (event) => {
  try {
    let query = event.queryStringParameters;
    let limit = query && query.limit ? parseInt(query.limit) : 10;

headersに指定している、user_idを取得します。

exports.handler = async (event) => {
  try {
    let query = event.queryStringParameters;
    let limit = query && query.limit ? parseInt(query.limit) : 10;
    let user_id = event.headers.user_id;

パラメータにTableNameKeyConditionExpressionExpressionAttributeValuesLimitScanIndexForwardを設定します。

KeyConditionExpressionは、クエリをじっっこうするキーを指定します。

ExpressionAttributeValuesで、KeyConditionExpressionの値を置換します。

ソートの順番を反転させたいので、ScanIndexForwardを false にします。

exports.handler = async (event) => {
  try {
    let query = event.queryStringParameters;
    let limit = query && query.limit ? parseInt(query.limit) : 10;
    let user_id = event.headers.user_id;

    let params = {
      TableName: tableName,
      KeyConditionExpression: "user_id = :uid",
      ExpressionAttributeValues: {
        ":uid": user_id,
      },
      Limit: limit,
      ScanIndexForward: false,
    };

11 件目からを表示できるように、最後のtimestampをパラメータで取得します。

パラメータがない場合、0 とします。

exports.handler = async (event) => {
  try {
    let query = event.queryStringParameters;
    let limit = query && query.limit ? parseInt(query.limit) : 10;
    let user_id = event.headers.user_id;

    let params = {
      TableName: tableName,
      KeyConditionExpression: "user_id = :uid",
      ExpressionAttributeValues: {
        ":uid": user_id,
      },
      Limit: limit,
      ScanIndexForward: false,
    };

    let timestamp = query && query.start ? parseInt(query.start) : 0;

timestampがある場合、ExclusiveStartKeyを設定します。

ExclusiveStartKeyとは、取得できた最後のパラメータが入っています。

exports.handler = async (event) => {
  try {
    let query = event.queryStringParameters;
    let limit = query && query.limit ? parseInt(query.limit) : 1;
    let user_id = event.headers.user_id;

    let params = {
      TableName: tableName,
      KeyConditionExpression: "user_id = :uid",
      ExpressionAttributeValues: {
        ":uid": user_id,
      },
      Limit: limit,
      ScanIndexForward: false,
    };

    let timestamp = query && query.start ? parseInt(query.start) : 0;

    if (timestamp > 0) {
      params.ExclusiveStartKey = {
        user_id,
        timestamp,
      };
    }

dynamodbqueryでパラメータを設定します。

exports.handler = async (event) => {
  try {
    let query = event.queryStringParameters;
    let limit = query && query.limit ? parseInt(query.limit) : 1;
    let user_id = event.headers.user_id;

    let params = {
      TableName: tableName,
      KeyConditionExpression: "user_id = :uid",
      ExpressionAttributeValues: {
        ":uid": user_id,
      },
      Limit: limit,
      ScanIndexForward: false,
    };

    let timestamp = query && query.start ? parseInt(query.start) : 0;

    if (timestamp > 0) {
      params.ExclusiveStartKey = {
        user_id,
        timestamp,
      };
    }

    let item = await dynamodb.query(params).promise();

ハンドラーが完成したので、serverless.yml の YAML を設定します。

provideriamRoleStatementsにあるActionに、Queryを設定します。

provider:
  name: aws
  runtime: nodejs14.x
  region: us-west-2
  stage: dev
  memorySize: 128
  timeout: 5
  endpointType: regional
  lambdaHashingVersion: 20201221
  environment:
    NOTES_TABLE: ${self:service}-${opt:stage, self:provider.stage}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:PutItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.NOTES_TABLE}"

functionsget-notesを設定します。

pathは、notesとします。

methodは、getとします。

get-notes:
  handler: api/get-notes.handler
  description: GET /notes
  events:
    - http:
        path: notes
        method: get
        cors:
          origin: "*"
          headers: ${self:custom.allowedHeaders}

一通り完成したので、ターミナルをプロジェクトのディレクトリに移動し、serverless offline を実行します。

ポストマンで、GET にし、http://localhost:3000/dev/notes  を指定します。

また、Content-Typeuser_iduser_nameを指定します。

image2

Send とクリックすると、

image3

データを表示することができました。

試しに、POST でいくつかデータを作成し、パラメータを操作してみます。

パラメータを『limit=1』にしてみます。

URL にパラメータを入れて、『Send』をクリックすると、

image4

データが 3 件ありますが、1 件だけ取得できました。

さらに、LastEvaluatedKeytimestampをパラメータに入れてみます。

URL のパラメータに、『start=1640740424』とします。

『Send』をクリックすると、

image5

次の 1 件(2 件目)が表示されました。

次回は、保存したデータから、単一データを取得します。

ブログ一覧