Writing Code for DynamoDB Queries & Scans
This tutorial references the code in the aws-connectedcar-dotnet-core repository. If you're new to this course, see the introduction for information about setting up your workstation and getting the sample code.
Next in our series of DynamoDB code tutorials, we’ll look at writing code to perform queries and scans.
Performing Table Scans
Generally speaking, you want to avoid using table scans in your code. This is because with table scans you’re sequentially reading all the items in a table, which is slower than using a query, and results in higher usage costs. Nonetheless, sometimes scans are the only option.
For example, in the sample code the Dealer table defines a stateCode attribute, and this attribute is not suited to being a hash key in a secondary index due to its limited distribution of values. As a result, the method to search for items in the Dealer table has to perform a table scan. (This is also a small table in terms of the number of items, and the results can be cached, so the performance and cost penalties are small).
Here’s the method in the DealerService class that performs this table scan:
In this code, line 72 defines the conditions list, which in this case only has one entry for the StateCode equality condition. This list is then passed to the ScanAsync method that performs the actual table scan, shown on line 74.
Performing Queries with Table Keys
What you see below is the code for the GetEvents method, from the EventService, showing the implementation for a basic query. Here, the Event table has a "vin" hash key and a "timestamp" range key. This query specifies the "vin" value for the vehicle and therefore returns all the related event items for a vehicle:
Here’s a similar query example from the RegistrationService, but this time with the addition of some post-query filtering of the results in code, shown on lines 112-115:
Performing Queries with Global Secondary Indexes
Here’s another example from the AppointmentService, this time showing a query that makes use of a global secondary index. Line 73 shows the construction of the compound key object that we outlined previously in the modelling lesson. Line 74 shows the config variable that identifies the name of the index. This config variable is included as a parameter for the query, directing it to use the specified index.
As noted, the DynamoDB table names are constructed in CloudFormation and are not known to the service code at build-time. So at runtime, these names must be accessed through configuration. The global secondary index names, on the other hand, are private to the tables in which they are defined, and so their names don’t change across environments.
All the queries shown so far have used simple equality in the criteria. The example below, from the TimeslotService, shows how you can use an expression to define more complex criteria. One quirk to note about this case is that on line 75 the attributes names specified in the expression need take the form of the serialized names in the table, rather than the property names from the mapped data classes:
This tutorial references the code in the aws-connectedcar-java-core repository. If you're new to this course, see the introduction for information about setting up your workstation and getting the sample code.
Next in our series of DynamoDB code tutorials, we’ll look at writing code to perform queries and scans.
Performing Table Scans
Generally speaking, you want to avoid using table scans in your code. This is because with table scans you’re sequentially reading all the items in a table, which is slower than using a query, and results in higher usage costs. Nonetheless, sometimes scans are the only option.
For example, in the sample code the Dealer table defines a stateCode attribute, and this attribute is not suited to being a hash key in a secondary index due to its limited distribution of values. As a result, the method to search for items in the Dealer table has to perform a table scan. (This is also a small table in terms of the number of items, and the results can be cached, so the performance and cost penalties are small).
Here’s the method in the DealerService class that performs this table scan:
In this code, lines 94-104 defines the query expression, which in this case only has one criteria for the StateCode equality condition. This expression is then added to the request on lines 106-108, which is passed as an input to the scan method of the table instance that performs the actual table scan, shown on line 110.
Performing Queries with Table Keys
What you see below is the code for the getEvents method, from the EventService, showing the implementation for a basic query. Here, the Event table has a "vin" hash key and a "timestamp" range key. This query specifies the "vin" value for the vehicle and therefore returns all the related event items for a vehicle:
Here’s a similar query example from the RegistrationService, but this time with the addition of some post-query filtering of the results in code, shown on lines 155-159:
Performing Queries with Global Secondary Indexes
Here’s another example from the AppointmentService, this time showing a query that makes use of a global secondary index. Lines 98-101 shows the construction of the compound key object that we outlined previously in the modelling lesson. Line 104 shows the creation of the index client object using the index name.
As noted, the DynamoDB table names are constructed in CloudFormation and are not known to the service code at build-time. So at runtime, these names must be accessed through configuration. The global secondary index names, on the other hand, are private to the tables in which they are defined, and so their names don’t change across environments.
All the queries shown so far have used simple equality in the criteria. The example below, from the TimeslotService, shows how you can query for the hash key value, and then filter within the range of results in code for criteria that the query interface doesn't support.