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!