[Lab] DymamoDB Pagination

If you send a GET request using this URL: https://{{apiId}}.execute-api.us-east-1.amazonaws.com/dev/groups?limit=2 you should get a reply like this:

{
    "items": [
      ...
    ],
    "nextKey": "%7B%22id%22%3A%221%22%7D"
}

Notice that you need to replace {{apiId}} with an id of the API that you've deployed.

If you pass the nextKey and use it with another GET request using this URL: https://{{apiId}}.execute-api.us-east-1.amazonaws.com/dev/groups?limit=2&nextKey=%7B%22id%22%3A%221%22%7D

{
    "items": [
      ...
    ],
    "nextKey": null
}

If nextKey is null it means that there are no more items to return.

Notice that the value of the LastEvaluatedKey in a DynamoDB result is a JSON object. To pass it in another GET request we convert it to a string and then use URI encoding to allow to pass it in a URL:

encodeURIComponent(JSON.stringify(lastEvaluatedKey))

To pass a value coming in a GET request you would need to first decode a string and then parse a JSON string:

// Value read from a query parameter
const nextKeyStr = ...
// "exclusiveStartKey" can be passed a parameter to a "scan()" call
const exclusiveStartKey = JSON.parse(decodeURIComponent(nextKeyStr))

 


 

'use strict'

const AWS = require('aws-sdk')

const docClient = new AWS.DynamoDB.DocumentClient()

const groupsTable = process.env.GROUPS_TABLE

exports.handler = async (event) => {
  console.log('Processing event: ', event)

  let nextKey // Next key to continue scan operation if necessary
  let limit // Maximum number of elements to return
  try {
    // Parse query parameters
    nextKey = parseNextKeyParameter(event)
    limit = parseLimitParameter(event) || 20
  } catch (e) {
    console.log('Failed to parse query parameters: ', e.message)
    return {
      statusCode: 400,
      headers: {
        'Access-Control-Allow-Origin': '*'
      },
      body: JSON.stringify({
        error: 'Invalid parameters'
      })
    }
  }

  // Scan operation parameters
  const scanParams = {
    TableName: groupsTable,
    Limit: limit,
    ExclusiveStartKey: nextKey
  }
  console.log('Scan params: ', scanParams)

  const result = await docClient.scan(scanParams).promise()

  const items = result.Items

  console.log('Result: ', result)

  // Return result
  return {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*'
    },
    body: JSON.stringify({
      items,
      // Encode the JSON object so a client can return it in a URL as is
      nextKey: encodeNextKey(result.LastEvaluatedKey)
    })
  }
}

/**
 * Get value of the limit parameter.
 *
 * @param {Object} event HTTP event passed to a Lambda function
 *
 * @returns {number} parsed "limit" parameter
 */
function parseLimitParameter(event) {
  const limitStr = getQueryParameter(event, 'limit')
  if (!limitStr) {
    return undefined
  }

  const limit = parseInt(limitStr, 10)
  if (limit <= 0) {
    throw new Error('Limit should be positive')
  }

  return limit
}

/**
 * Get value of the limit parameter.
 *
 * @param {Object} event HTTP event passed to a Lambda function
 *
 * @returns {Object} parsed "nextKey" parameter
 */
function parseNextKeyParameter(event) {
  const nextKeyStr = getQueryParameter(event, 'nextKey')
  if (!nextKeyStr) {
    return undefined
  }

  const uriDecoded = decodeURIComponent(nextKeyStr)
  return JSON.parse(uriDecoded)
}

/**
 * Get a query parameter or return "undefined"
 *
 * @param {Object} event HTTP event passed to a Lambda function
 * @param {string} name a name of a query parameter to return
 *
 * @returns {string} a value of a query parameter value or "undefined" if a parameter is not defined
 */
function getQueryParameter(event, name) {
  const queryParams = event.queryStringParameters
  if (!queryParams) {
    return undefined
  }

  return queryParams[name]
}

/**
 * Encode last evaluated key using
 *
 * @param {Object} lastEvaluatedKey a JS object that represents last evaluated key
 *
 * @return {string} URI encoded last evaluated key
 */
function encodeNextKey(lastEvaluatedKey) {
  if (!lastEvaluatedKey) {
    return null
  }

  return encodeURIComponent(JSON.stringify(lastEvaluatedKey))
}

  

 

posted @ 2021-05-02 16:57  Zhentiw  阅读(71)  评论(0编辑  收藏  举报