Skip to main content

Query

Dynamode provides the ability to query your items. Query class allows you to retrieve multiple items that have the same partition key but different sort keys.

Query class acts as a build to construct your query with appropriate filters, to run it use Query.run(options?) method.

Condition

Query is a child of Condition class, meaning that all methods listed on Condition page are also available in Query class. As example you can use Query.attribute(key) method to filter out retrieved items.

new Query(Entity) or EntityManager.query()

Every query has to be initialized with Entity to infer its underlying properties. You can achieve this in two ways:

// Below definitions are equivalent
new Query(AllPossibleProperties);
AllPossiblePropertiesManager.query();

AllPossibleProperties is an example class that extends Entity.

Query.partitionKey(key)

This method prepares a partition key conditional expression. The key parameter is a string, narrowed down to entity partition keys.

info

These properties are allowed for the AllPossibleProperties model

AllPossiblePropertiesManager.query().partitionKey('partitionKey');
AllPossiblePropertiesManager.query().partitionKey('GSI_1_PK');
caution

Typescript error: Argument of type '"unknownProperty"' is not assignable to parameter of type: "partitionKey" | "GSI_1_PK"

AllPossiblePropertiesManager.query().partitionKey('unknownProperty');

To complete partition key conditional you need to use .eq(value) function.

.eq(value)

This comparison function will check if the given key is equal to the value that is passed in as a parameter.

UserManager.query().partitionKey('partitionKey').eq('1'); // Resulting in: `partitionKey = 1`

Query.sortKey(key)

This method prepares a sort key conditional expression. The key parameter is a string, narrowed down to entity sort keys.

info

These properties are allowed for the AllPossibleProperties model

AllPossiblePropertiesManager.query().sortKey('sortKey');
AllPossiblePropertiesManager.query().sortKey('GSI_1_SK');
AllPossiblePropertiesManager.query().sortKey('LSI_1_SK');
caution

Typescript error: Argument of type '"unknownProperty"' is not assignable to parameter of type: "sortKey" | "GSI_1_SK" | "LSI_1_SK"

AllPossiblePropertiesManager.query().sortKey('unknownProperty');

To complete sort key conditional you need to use one of undermentioned functions.

UserManager.query().sortKey('sortKey'); // This condition has no impact on the final conditional
UserManager.query().sortKey('sortKey').eq('blazej'); // Adding comparison function (eq) after `sortKey(key)` method will complete the conditional. Resulting in: `sortKey = blazej`

.eq(value)

This comparison function will check if the given key is equal to the value that is passed in as a parameter.

UserManager.query().sortKey('sortKey').eq('blazej'); // Resulting in: `sortKey = blazej`

.ne(value)

This comparison function will check if the given key is not equal to the value that is passed in as a parameter.

UserManager.query().sortKey('sortKey').ne('blazej'); // Resulting in: `sortKey <> blazej`

.lt(value)

This comparison function will check if the given key is less than the value that is passed in as a parameter.

UserManager.query().sortKey('sortKey').lt('blazej'); // Resulting in: `sortKey < blazej`

.le(value)

This comparison function will check if the given key is less than or equal to the value that is passed in as a parameter.

UserManager.query().sortKey('sortKey').le('blazej'); // Resulting in: `sortKey <= blazej`

.gt(value)

This comparison function will check if the given key is greater than the value that is passed in as a parameter.

UserManager.query().sortKey('sortKey').gt('blazej'); // Resulting in: `sortKey > blazej`

.ge(value)

This comparison function will check if the given key is greater than or equal to the value that is passed in as a parameter.

UserManager.query().sortKey('sortKey').ge('blazej'); // Resulting in: `sortKey >= blazej`

.beginsWith(value)

This comparison function will check if the given key is begins with the value that is passed in as a parameter.

UserManager.query().sortKey('sortKey').beginsWith('bla'); // Resulting in: `begins_with(sortKey, bla)`

.between(value1, value2)

This comparison function will check if the given key is between the values that were passed in as parameters.

UserManager.query().sortKey('sortKey').between('bla', 'cla'); // Resulting in: `sortKey BETWEEN 'bla' AND 'cla'`

Query.indexName(name)

The name of a secondary index to query. This index can be any local secondary index or global secondary index. The name parameter is a string, narrowed down to entity index names. It uses DynamoDB's IndexName.

UserManager.query().partitionKey('partitionKey').eq('1').indexName('LSI_1_NAME') // Resulting in: `IndexName: LSI_1_NAME`

Query.sort(order)

This method sorts the items you receive by using sort key. It uses DynamoDB's ScanIndexForward.

The order parameter must be a string, either 'ascending' or 'descending'. Query will return items in ascending order by default.

UserManager.query().partitionKey('partitionKey').eq('1').sort('descending'); // Resulting in: `ScanIndexForward: false`

Query.limit(count)

This method will limit the number of items that DynamoDB query in one request. It uses DynamoDB's Limit.

caution

Unlike most SQL databases this does not guarantee the response will contain 5 items. DynamoDB will only query a maximum of 5 items and check if they match and should be returned.

The count argument should be a number representing how many items you wish DynamoDB to query.

UserManager.query().partitionKey('partitionKey').eq('1').limit(10); // Resulting in: `Limit: 10`

Query.startAt(key)

In case there are more items to retrieve in a previous query response, Dynamode will return lastKey property with primary key of last evaluated item. You can pass this property to further query your items. It uses DynamoDB's LastEvaluatedKey.

const response1 = await UserManager.query().partitionKey('partitionKey').eq('1').run(); 
const response2 = await UserManager.query().partitionKey('partitionKey').eq('1').startAt(response1.lastKey).run(); // Resulting in: `LastEvaluatedKey: response1.lastKey`

Query.consistent()

This will cause the query to run a consistent read. By default read is eventually consistent. It uses DynamoDB's ConsistentRead.

UserManager.query().partitionKey('partitionKey').eq('1').consistent(); // Resulting in: `ConsistentRead: true`

Query.count()

Instead of returning an array of items, this method will make the query operation to return an object with count information. This option saves bandwidth by using DynamoDB's Select.

UserManager.query().partitionKey('partitionKey').eq('1').count(); // Resulting in: `Select: 'COUNT'`

Query.attributes(attributes)

This method is used to tag what item attributes should be retrieved and returned. This uses DynamoDB's ProjectionExpression.

If this value is undefined, then all attributes will be returned. attributes argument should be an array of strings representing the property names to return.

UserManager.query().partitionKey('partitionKey').eq('1').attributes(['username', 'age']); // Resulting in: `ProjectionExpression: 'username, age'`

Query.run(options?)

Description

This method is used to execute constructed query and retrieve multiple items from DynamoDB. It uses the Query DynamoDB operation.

By default it makes one DynamoDB API call, but you can change it by passing all option described below. With all set to true this function will send continuous query requests until all items are retrieved.

Arguments

You can add optional options parameter that is an object. The table below represents options that you can pass in:

NameDescriptionTypeDefault
returnWhat the method should return. For 'default' method returns initialized classes with retrieved data. For 'input' method returns prepared DynamoDB input command and no request is made to DynamoDB (method no longer returns a promise). For 'output' method returns the bare output from DynamoDB operation.'default' | 'input' | 'output''default'
allIn case it is set to true this method will send continuous query requests until all items are retrieved (it checks lastKey property from previous responses). This can be useful for getting all items autonomously in case you don't want to check lastKey property manually and send multiple requests yourself.booleanfalse
maxUse only if all option is set to true. The maximum number of items that should be retrieved, regardless if the lastKey property still exists in the response. As default an unlimited number of items will be retrieved to the point that lastKey property no longer exists.numberInfinity
delayUse only if all option is set to true. Number of milliseconds to delay between receiving a response to the next query request.number0
extraInputExtra input that is passed to QueryInput DynamoDB operation. Use it only in case that you know what are you are doing as it may override other properties passed to DynamoDB operation.QueryInputundefined

If all option is set to true all of the requests will be merged into a single array. count and scannedCount properties will be summed in the response. If you pass max option and there is still a lastKey in the response it will be returned to you.

Examples

const result = await UserManager.query()
.partitionKey('partitionKey').eq('1')
.sortKey('sortKey').beginsWith('bla')
.limit(1).sort('descending')
.run();
// OR
const result = await UserManager.query()
.partitionKey('partitionKey').eq('1')
.sortKey('sortKey').beginsWith('bla')
.limit(1).sort('descending')
.run({ return: 'default' });

Output:

{
items: [
User {
dynamodeEntity: 'User',
partitionKey: '1',
sortKey: 'blazej3',
username: 'blazej',
email: 'blazej@gmail.com',
age: 18,
friends: [Array],
config: [Object]
}
],
count: 1,
scannedCount: 1,
lastKey: { partitionKey: '1', sortKey: 'blazej3' }
}