Menu
Amazon DynamoDB
Developer Guide (API Version 2012-08-10)

Querying Using the AWS SDK for Java Document API

The Query API enables you to query a table or a secondary index. You must provide a hash key value and an equality condition. If the table or index has a range key, you can refine the results by providing a range key value and a condition.

Note

This section explains the AWS SDK for Java Document API. The AWS SDK for Java also provides a high-level object persistence model, enabling you to map your client-side classes to DynamoDB tables. This approach can reduce the amount of code you have to write. For more information, see Java: Object Persistence Model.

The following are the steps to retrieve an item using the AWS SDK for Java Document API.

  1. Create an instance of the DynamoDB class.

  2. Create an instance of the Table class to represent the table you want to work with.

  3. Call the query method of the Table instance. You must specify the hash key of the item(sK) that you want to retrieve, along with any optional query parameters.

The response includes an ItemCollection object that provides all items returned by the query.

The following Java code snippet demonstrates the preceding tasks. The snippet assumes you have a Reply table that stores replies for forum threads. For more information, see Example Tables and Data.

Reply ( Id, ReplyDateTime, ... )

Each forum thread has a unique ID and can have zero or more replies. Therefore, the Id attribute of the Reply table is composed of both the forum name and forum subject. The Id and the ReplyDateTime make up the composite hash-and-range primary key for the table.

The following query retrieves all replies for a specific thread subject. The query requires both the table name and the Subject value.


DynamoDB dynamoDB = new DynamoDB(
    new AmazonDynamoDBClient(new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("Reply");

Map<String, Object> valueMap = new HashMap<String, Object>();
valueMap.put(":v_id", "Amazon DynamoDB#DynamoDB Thread 1");

QuerySpec spec = new QuerySpec()
    .withKeyConditionExpression("Id = :v_id")
    .withValueMap(new ValueMap()
        .withString(":v_id", "Amazon DynamoDB#DynamoDB Thread 1"));

ItemCollection<QueryOutcome> items = table.query(spec);

Iterator<Item> iterator = items.iterator();
Item item = null;
while (iterator.hasNext()) {
    item = iterator.next();
    System.out.println(item.toJSONPretty());
}

Specifying Optional Parameters

The query method supports several optional parameters. For example, you can optionally narrow the results from the preceding query to return replies in the past two weeks by specifying a condition. The condition is called a range condition because DynamoDB evaluates the query condition that you specify against the range attribute of the primary key. You can specify other optional parameters to retrieve only a specific list of attributes from items in the query result.

The following Java code snippet retrieves forum thread replies posted in the past 15 days. The snippet specifies optional parameters using:

  • A KeyConditionExpression to retrieve the replies from a specific discussion forum (hash key) and, within that set of items, replies that were posted within the last 15 days (range key).

  • A FilterExpression to return only the replies from a specific user. The filter is applied after the query is processed, but before the results are returned to the user.

  • A ValueMap to define the actual values for the KeyConditionExpression placeholders.

  • A ConsistentRead setting of true, to request a strongly consistent read. To learn more about read consistency, see DynamoDB Data Model.

This snippet uses a QuerySpec object which gives access to all of the low-level Query input parameters.


Table table = dynamoDB.getTable("Reply");

long twoWeeksAgoMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L);
Date twoWeeksAgo = new Date();
twoWeeksAgo.setTime(twoWeeksAgoMilli);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
String twoWeeksAgoStr = df.format(twoWeeksAgo);

QuerySpec spec = new QuerySpec()
    .withKeyConditionExpression("Id = :v_id and ReplyDateTime > :v_reply_dt_tm")
    .withFilterExpression("PostedBy = :v_posted_by")
    .withValueMap(new ValueMap()
        .withString(":v_id", "Amazon DynamoDB#DynamoDB Thread 1")
        .withString(":v_reply_dt_tm", twoWeeksAgoStr)
        .withString(":v_posted_by", "User B"))
    .withConsistentRead(true);

ItemCollection<QueryOutcome> items = table.query(spec);

Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next().toJSONPretty());
}

You can also optionally limit the number of items per page by using the withMaxPageSize method. When time you call the query method, you get an ItemCollection that contains the resulting items. You can then step through the results, processing one page at a time, until there are no more pages.

The following Java code snippet modifies the query specification shown above. This time, the query spec uses the withMaxPageSize method. The Page class provides an Iterator that allows the code to process the items on each page.


spec.withMaxPageSize(10);

ItemCollection<QueryOutcome> items = table.query(spec);

// Process each page of results
int pageNum = 0;
for (Page<Item, QueryOutcome> page : items.pages()) {
        
    System.out.println("\nPage: " + ++pageNum);

    // Process each item on the current page
    Iterator<Item> item = page.iterator();
    while (item.hasNext()) {
        System.out.println(item.next().toJSONPretty());
    }
}

Example - Query Using Java

The following tables store information about a collection of forums. For more information about table schemas, see Example Tables and Data.

Note

This section explains the AWS SDK for Java Document API. The AWS SDK for Java also provides a high-level object persistence model, enabling you to map your client-side classes to DynamoDB tables. This approach can reduce the amount of code you have to write. For more information, see Java: Object Persistence Model.

For a code example that demonstrates query operations using the object persistence model, see Example: Query and Scan.

Forum ( Name, ... ) 
Thread ( ForumName, Subject, Message, LastPostedBy, LastPostDateTime, ...) 
Reply ( Id, ReplyDateTime, Message, PostedBy, ...)

In this Java code example, you execute variations of finding replies for a thread 'DynamoDB Thread 1' in forum 'DynamoDB'.

  • Find replies for a thread.

  • Find replies for a thread, specifying a limit on the number of items per page of results. If the number of items in the result set exceeds the page size, you get only the first page of results. This coding pattern ensures your code processes all the pages in the query result.

  • Find replies in the last 15 days.

  • Find replies in a specific date range.

    Both the preceding two queries shows how you can specify range key conditions to narrow the query results and use other optional query parameters.

Note

This code example assumes that you have already loaded data into DynamoDB for your account by following the instructions in the Creating Tables and Loading Sample Data section. Alternatively, you can load the data programmatically using the instructions in the Creating Example Tables and Uploading Data Using the AWS SDK for Java topic.

For step-by-step instructions to run the following example, see Running Java Examples for DynamoDB.

// Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
package com.amazonaws.codesamples.document;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.Page;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

public class DocumentAPIQuery {

    static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));

    static String tableName = "Reply";

    public static void main(String[] args) throws Exception {
        
        String forumName = "Amazon DynamoDB";
        String threadSubject = "DynamoDB Thread 1";

        findRepliesForAThread(forumName, threadSubject);
        findRepliesForAThreadSpecifyOptionalLimit(forumName, threadSubject);
        findRepliesInLast15DaysWithConfig(forumName, threadSubject);
        findRepliesPostedWithinTimePeriod(forumName, threadSubject);
        findRepliesUsingAFilterExpression(forumName, threadSubject);
    }
    
    private static void findRepliesForAThread(String forumName, String threadSubject) {

        Table table = dynamoDB.getTable(tableName);

        String replyId = forumName + "#" + threadSubject;
        
        QuerySpec spec = new QuerySpec()
            .withKeyConditionExpression("Id = :v_id")
            .withValueMap(new ValueMap()
                .withString(":v_id", replyId));
        
        ItemCollection<QueryOutcome> items = table.query(spec);
        
        System.out.println("\nfindRepliesForAThread results:");

        Iterator<Item> iterator = items.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
        }
        
    }

    private static void findRepliesForAThreadSpecifyOptionalLimit(String forumName, String threadSubject) {

        Table table = dynamoDB.getTable(tableName);
        
        String replyId = forumName + "#" + threadSubject;   
               
        QuerySpec spec = new QuerySpec()
            .withKeyConditionExpression("Id = :v_id")
            .withValueMap(new ValueMap()
                .withString(":v_id", replyId))
            .withMaxPageSize(1);

        ItemCollection<QueryOutcome> items = table.query(spec);
        
        System.out.println("\nfindRepliesForAThreadSpecifyOptionalLimit results:");

        // Process each page of results
        int pageNum = 0;
        for (Page<Item, QueryOutcome> page : items.pages()) {
            
            System.out.println("\nPage: " + ++pageNum);

            // Process each item on the current page
            Iterator<Item> item = page.iterator();
            while (item.hasNext()) {
                System.out.println(item.next().toJSONPretty());
            }
        }
    }
    
    private static void findRepliesInLast15DaysWithConfig(String forumName, String threadSubject) {

        Table table = dynamoDB.getTable(tableName);

        long twoWeeksAgoMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L);
        Date twoWeeksAgo = new Date();
        twoWeeksAgo.setTime(twoWeeksAgoMilli);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String twoWeeksAgoStr = df.format(twoWeeksAgo);
        
        String replyId = forumName + "#" + threadSubject;

        QuerySpec spec = new QuerySpec()
            .withProjectionExpression("Message, ReplyDateTime, PostedBy")
            .withKeyConditionExpression("Id = :v_id and ReplyDateTime <= :v_reply_dt_tm")
            .withValueMap(new ValueMap()
                .withString(":v_id", replyId)
                .withString(":v_reply_dt_tm", twoWeeksAgoStr));
        
        ItemCollection<QueryOutcome> items = table.query(spec);

        System.out.println("\nfindRepliesInLast15DaysWithConfig results:");
        Iterator<Item> iterator = items.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
        }

    }
    
    private static void findRepliesPostedWithinTimePeriod(String forumName, String threadSubject) {

        Table table = dynamoDB.getTable(tableName);

        long startDateMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L); 
        long endDateMilli = (new Date()).getTime() - (5L*24L*60L*60L*1000L);    
        java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String startDate = df.format(startDateMilli);
        String endDate = df.format(endDateMilli);

        String replyId = forumName + "#" + threadSubject;

        QuerySpec spec = new QuerySpec()
            .withProjectionExpression("Message, ReplyDateTime, PostedBy")
            .withKeyConditionExpression("Id = :v_id and ReplyDateTime between :v_start_dt and :v_end_dt")
            .withValueMap(new ValueMap()
                .withString(":v_id", replyId)
                .withString(":v_start_dt", startDate)
                .withString(":v_end_dt", endDate));
        
        ItemCollection<QueryOutcome> items = table.query(spec);

        System.out.println("\nfindRepliesPostedWithinTimePeriod results:");
        Iterator<Item> iterator = items.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
        }    
    }

    private static void findRepliesUsingAFilterExpression(String forumName, String threadSubject) {

        Table table = dynamoDB.getTable(tableName);
        
        String replyId = forumName + "#" + threadSubject;

        QuerySpec spec = new QuerySpec()
            .withProjectionExpression("Message, ReplyDateTime, PostedBy")
            .withKeyConditionExpression("Id = :v_id")
            .withFilterExpression("PostedBy = :v_postedby")
            .withValueMap(new ValueMap()
                .withString(":v_id", replyId)
                .withString(":v_postedby", "User B"));
        
        ItemCollection<QueryOutcome> items = table.query(spec);

        System.out.println("\nfindRepliesUsingAFilterExpression results:");
        Iterator<Item> iterator = items.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
        }    
     }
    
}