1
votes

How to create a dynamic function using Node.js to retrieve data from AWS DynamoDB using the query method? The function should be able to get parameters like TableName, IndexName, Key, Value, SortKey, SortValue, Filter, FilterValue, SecondFilter, SecondFildValue, ScanIndexForward, Limit. And it will be great to support the ability to get all items from the table, as Dynamo DB query retrieves only the part of items.

Thanks in advance.

3
What have you tried? Where are you stuck? As it stands, this question sounds like you want someone to do the work for you. - Mark B

3 Answers

2
votes

For my personal usage, I'm actually using the following lib.

Here you can find the getItemByGSI function which receives many parameters to customize Query.

TableName - Name of you Dynamodb table: required type String

IndexName - Name of your Index from Dynamodb table: optional

attribute - Key for query: required

value - Value for Key: required

sortKey - optional type String

sortValue - Value for SortKey: optional

filter - Filter for using in FilterExpression: optional type String

filterValue - Value for Filter: optional

operator - Operator for Filters if you have more than 1 filter. Required if you have filter1 and filterValue1: optional type String

filter1 - Second Filter for using in FilterExpression: optional type String

filterValue1 - Value for Filter1: optional

LastEvaluatedKey - Use LastEvaluatedKey to get next items. You can get LastEvaluatedKey from the first request if You have more items in Table for one query: optional type Object

ScanIndexForward - Use ScanIndexForward for ordering items. For sure items be ordered if you have a sort Key. ScanIndexForward: false for Descending. By default its Ascending: optional type Boolean

Limit - Use Limit for getting Limited Items: optional type Number

Use getAllItemsByGSI to retrieve all items from the DynamoDB table using recursive queries. It can receive the same parameters as getItemByGSI.

'use strict';
    
    const omitBy = require('lodash/omitBy');
    const isNil = require('lodash/isNil');
    const AWS = require('aws-sdk');
    
    const call = (action, params) => {
        return new Promise((resolve, reject) => {
            try {
                const dynamoDb = new AWS.DynamoDB.DocumentClient();
                resolve(dynamoDb[action](params).promise());
            } catch (error) {
                reject(error);
            }
        });
    };
    
    const getItemByGSI = ({
        TableName,
        IndexName,
        attribute,
        value,
        sortKey,
        sortValue,
        filter,
        filterValue,
        operator,
        filter1,
        filterValue1,
        LastEvaluatedKey,
        ScanIndexForward,
        Limit,
    }) => {
        return new Promise(async (resolve, reject) => {
            try {
                const params = {
                    TableName,
                    IndexName,
                    KeyConditionExpression: '#attrKey = :attrValue',
                    ExpressionAttributeValues: { ':attrValue': value },
                    ExpressionAttributeNames: { '#attrKey': attribute },
                    ExclusiveStartKey: LastEvaluatedKey,
                    Limit,
                    FilterExpression: null,
                };
                sortKey && sortValue
                    ? (params.KeyConditionExpression +=
                            ' and #sortKey = :sortValue' &&
                            (params.ExpressionAttributeNames['#sortKey'] = sortKey) &&
                            (params.ExpressionAttributeValues[':sortKey'] = sortValue))
                    : '';
                filter && filterValue
                    ? (params.FilterExpression = `#${filter} = :${filter}`) &&
                      (params.ExpressionAttributeNames[`#${filter}`] = filter) &&
                      (params.ExpressionAttributeValues[`:${filter}`] = filterValue)
                    : '';
                filter && filterValue && operator && filter1 && filterValue1
                    ? (params.FilterExpression += ` ${operator} #${filter1} = :${filter1}`) &&
                      (params.ExpressionAttributeNames[`#${filter1}`] = filter1) &&
                      (params.ExpressionAttributeValues[`:${filter1}`] = filterValue1)
                    : '';
                params = omitBy(params, isNil);
                if (ScanIndexForward === false)
                    params.ScanIndexForward = ScanIndexForward;
                const result = await call('query', params);
                resolve(result);
            } catch (error) {
                reject(error);
            }
        });
    };
    
    const getAllItemsByGSI = (data) => {
        return new Promise(async (resolve, reject) => {
            try {
                const finalData = [];
                const gettingData = await getItemByGSI(data);
                finalData = finalData.concat(gettingData.Items);
                if (gettingData.LastEvaluatedKey) {
                    const final2 = await getAllItemsByGSI({
                        ...data,
                        LastEvaluatedKey: gettingData.LastEvaluatedKey,
                    });
                    finalData = finalData.concat(final2);
                }
                resolve(finalData);
            } catch (err) {
                reject(err);
            }
        });
    };
    
    module.exports = {
        getItemByGSI,
        getAllItemsByGSI,
    };

Examples of usage

await getItemByGSI({
      TableName : 'Example',
      IndexName: 'favorite-createdAt-index',
      attribute: 'favorite',
      value: 'true',
      ScanIndexForward: false,
      Limit: 50
})

Hope it can be helpful!

4
votes

Have you looked at the JavaScript examples in the AWS github example repo? If not, you will find them here: https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javascriptv3/example_code/dynamodb/src

2
votes

Here is an example, which you can modify and add needed parameters.

/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
ABOUT THIS NODE.JS EXAMPLE: This example works with AWS SDK for JavaScript version 3 (v3),
which is available at https://github.com/aws/aws-sdk-js-v3. This example is in the 'AWS SDK for JavaScript v3 Developer Guide' at
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-query-scan.html.
Purpose:
ddb_query.ts demonstrates how to find items in an Amazon DynamoDB table.
Inputs (replace in code):
- REGION
Running the code:
ts-node ddb_query.ts
*/
// snippet-start:[dynamodb.JavaScript.table.queryV3]

// Import required AWS SDK clients and commands for Node.js
const { DynamoDBClient, QueryCommand } = require("@aws-sdk/client-dynamodb");

// Set the AWS Region
const REGION = "region"; //e.g. "us-east-1"

// Set the parameters
const params = {
  KeyConditionExpression: "Season = :s and Episode > :e",
  FilterExpression: "contains (Subtitle, :topic)",
  ExpressionAttributeValues: {
    ":s": { N: "1" },
    ":e": { N: "2" },
    ":topic": { S: "SubTitle" },
  },
  ProjectionExpression: "Episode, Title, Subtitle",
  TableName: "EPISODES_TABLE",
};

// Create DynamoDB service object
const dbclient = new DynamoDBClient({ region: REGION });
const run = async () => {
  try {
    const results = await dbclient.send(new QueryCommand(params));
    results.Items.forEach(function (element, index, array) {
      console.log(element.Title.S + " (" + element.Subtitle.S + ")");
    });
  } catch (err) {
    console.error(err);
  }
};
run();
// snippet-end:[dynamodb.JavaScript.table.queryV3]