10110
10110

Reputation: 2695

Query() DynamoDB for each value in array on Lambda NodeJS

I have the following code in a NodeJS 12x Lambda function:

targetedAliases = ["abc", "efg"]; //Not used yet. But want to replace alias with this array.
alias = "abc" //using this one aka targetedAliases[0].

const dynamoDB = new AWS.DynamoDB({
    apiVersion: "2012-10-08"
});
var aliasScores;


const params = {
    TableName: 'a-table',
    FilterExpression: '#alias = :alias',
    ExpressionAttributeNames: {
        '#alias': 'alias',
    },
    ExpressionAttributeValues: {
        ':alias': {
            S: alias
        },
    }
};

aliasScores = await dynamoDB.scan(params).promise();

console.log("====> ", aliasScores);

The function as is prints the content of aliasScores as expected but I need to execute this n times for each item on the targetedAliases array.

Is there a way I can use a Array.forEach or something similar to execute a query/scan iteratively for each item in an array? Alternatively, can I use an array on the FilterExpression to execute the query/scan just once?

I want store each query/scan result in the aliasScores variable as a concatenation of all returned objects to use it further below.

Upvotes: 0

Views: 1751

Answers (2)

starpebble
starpebble

Reputation: 544

Your options kinda depend on whether the attribute alias is a primary key or not. Just knowing this difference will help a lot.

Promise.all() executes one operation for each alias. Consider the batch approach. A single batch for executes in one API invocation which will reduce the number of operations and reduce your DynamoDB API calls. Batching is fun.

When the attribute key 'alias' is the primary key, BatchGetItem a is very efficient operation for up to a dozen or so operations where each operation is a query for one alias. Just create a single BatchGetItem with one operation for each entry in the array. The response is a single json dictionary.

When the attribute key 'alias' is not the primary key then it's different because the table must be scanned. A DynamoDB scan() is different than a DynamoDB query(). scan can find items by any attribute and can filter by the value of 'alias.' The FilterExpression supports OR and it is possible to filter the scan. The scan will check every item and the filter just reduces the returned result set. The response is a single json dictionary.

Upvotes: 1

Ashish Modi
Ashish Modi

Reputation: 7770

You can use Promise.all with .map to execute these in parallel and get the results in array. Something like this

const targetedAliases = ["abc", "efg"]; //Not used yet. But want to replace alias with this array.
alias = "abc" //using this one aka targetedAliases[0].

const dynamoDB = new AWS.DynamoDB({
    apiVersion: "2012-10-08"
});
var aliasScores;

const result = await Promise.all(targetedAliases.map(alias => {
  const params = {
    TableName: 'a-table',
    FilterExpression: '#alias = :alias',
    ExpressionAttributeNames: {
        '#alias': 'alias',
    },
    ExpressionAttributeValues: {
        ':alias': {
            S: alias
        },
    }
};

return dynamoDB.scan(params).promise();
}));

console.log(result);

Upvotes: 3

Related Questions