Amazon DynamoDB
Developer Guide (API Version 2012-08-10)
« PreviousNext »
View the PDF for this guide.Go to the AWS Discussion Forum for this product.Go to the Kindle Store to download this guide in Kindle format.Did this page help you?  Yes | No |  Tell us about it...

Table.Query Helper Method in the AWS SDK for .NET

The Query method enables you to query your tables. You can only query the tables that have a primary key that is composed of both a hash and range attribute. If your table's primary key is made of only a hash attribute, then the Query operation is not supported. By default, the API internally performs queries that are eventually consistent. To learn about the consistency model, see Data Read and Consistency Considerations.

The Query method provides two overloads. The minimum required parameters to the Query method are a hash key value and a range filter. You can use the following overload to provide these minimum required parameters.

Query(Primitive hashKey, RangeFilter Filter);

For example, the following C# code snippet queries for all forum replies that were posted in the last 15 days.

string tableName = "Reply"; 
Table table = Table.LoadTable(client, tableName);

DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);
RangeFilter filter = new RangeFilter(QueryOperator.GreaterThan, twoWeeksAgoDate);
Search search = table.Query("DynamoDB Thread 2", filter);

This creates a Search object. You can now call the Search.GetNextSet method iteratively to retrieve one page of results at a time as shown in the following C# code snippet. The code prints the attribute values for each item that the query returns.

List<Document> documentSet = new List<Document>();
do
{
  documentSet = search.GetNextSet();
  foreach (var document in documentSet)
    PrintDocument(document);
} while (!search.IsDone);

    private static void PrintDocument(Document document)
{
  Console.WriteLine();
  foreach (var attribute in document.GetAttributeNames())
  {
    string stringValue = null;
    var value = document[attribute];
    if (value is Primitive)
      stringValue = value.AsPrimitive().Value;
    else if (value is PrimitiveList)
      stringValue = string.Join(",", (from primitive
                                        in value.AsPrimitiveList().Entries
                                      select primitive.Value).ToArray());
    Console.WriteLine("{0} - {1}", attribute, stringValue);
  }
}

Specifying Optional Parameters

You can also specify optional parameters for Query, such as specifying a list of attributes to retrieve, strongly consistent reads, page size, and the number of items returned per page. For a complete list of parameters, see Query. To specify optional parameters, you must use the following overload in which you provide the QueryOperationConfig object.

Query(QueryOperationConfig config);

Assume that you want to execute the query in the preceding example (retrieve forum replies posted in the last 15 days). However, assume that you want to provide optional query parameters to retrieve only specific attributes and also request a strongly consistent read. The following C# code snippet constructs the request using the QueryOperationConfig object.

Table table = Table.LoadTable(client, "Reply");
DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);
QueryOperationConfig config = new QueryOperationConfig()
{
  HashKey = "DynamoDB Thread 2",
  AttributesToGet = new List<string> { "Subject", "ReplyDateTime", 
                                             "PostedBy" },
  ConsistentRead = true,
  Filter = new RangeFilter(QueryOperator.GreaterThan, twoWeeksAgoDate)
};

Search search = table.Query(config);

Example: Query using the Table.Query helper method

The following C# code example uses the Table.Query method to execute the following sample queries:

  • The following queries are executed against the Reply table.

    • Find forum thread replies that were posted in the last 15 days.

      This query is executed twice. In the first Table.Query call, the example provides only the required query parameters. In the second Table.Query call, you provide optional query parameters to request a strongly consistent read and a list of attributes to retrieve.

    • Find forum thread replies posted during a period of time.

      This query uses the Between query operator to find replies posted in between two dates.

  • Get a product from the ProductCatalog table.

    Because the ProductCatalog table has a primary key that is only a hash attribute, you can only get items; you cannot query the table. The example retrieves a specific product item using the item Id.

using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace Amazon.DynamoDBv2.Documentation
{
  class Program
  {
    private static AmazonDynamoDBClient client;

    static void Main(string[] args)
    {
      try
      {
        var config = new AmazonDynamoDBConfig();
        config.ServiceURL = System.Configuration.ConfigurationManager.AppSettings["ServiceURL"];
        client = new AmazonDynamoDBClient(config);

        // Query examples.
        Table replyTable = Table.LoadTable(client, "Reply");
        string forumName = "Amazon DynamoDB";
        string threadSubject = "DynamoDB Thread 2";
        FindRepliesInLast15Days(replyTable, forumName, threadSubject);
        FindRepliesInLast15DaysWithConfig(replyTable, forumName, threadSubject);
        FindRepliesPostedWithinTimePeriod(replyTable, forumName, threadSubject);

        // Get Example.
        Table productCatalogTable = Table.LoadTable(client, "ProductCatalog");
        int productId = 101;
        GetProduct(productCatalogTable, productId);

        Console.WriteLine("To continue, press Enter");
        Console.ReadLine();
      }
      catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
    }

    private static void GetProduct(Table tableName, int productId)
    {
      Console.WriteLine("*** Executing GetProduct() ***");
      Document productDocument = tableName.GetItem(productId);
      PrintDocument(productDocument);
    }

    private static void FindRepliesInLast15Days(Table table, string forumName, string threadSubject)
    {
      string hashAttribute = forumName + "#" + threadSubject;

      DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);
      QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, hashAttribute);
      filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan, twoWeeksAgoDate);

      // Use Query overloads that takes the minimum required query parameters.
      Search search = table.Query(filter);

      List<Document> documentSet = new List<Document>();
      do
      {
        documentSet = search.GetNextSet();
        Console.WriteLine("\nFindRepliesInLast15Days: printing ............");
        foreach (var document in documentSet)
          PrintDocument(document);
      } while (!search.IsDone);
    }

    private static void FindRepliesPostedWithinTimePeriod(Table table, string forumName, string threadSubject)
    {
      DateTime startDate = DateTime.UtcNow.Subtract(new TimeSpan(21, 0, 0, 0));
      DateTime endDate = DateTime.UtcNow.Subtract(new TimeSpan(1, 0, 0, 0));

      QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#" + threadSubject);
      filter.AddCondition("ReplyDateTime", QueryOperator.Between, startDate, endDate);

      QueryOperationConfig config = new QueryOperationConfig()
      {
        Limit = 2, // 2 items/page.
        Select = SelectValues.SpecificAttributes,
        AttributesToGet = new List<string> { "Message", 
                                             "ReplyDateTime", 
                                             "PostedBy" },
        ConsistentRead = true,
        Filter = filter
      };

      Search search = table.Query(config);

      List<Document> documentList = new List<Document>();

      do
      {
        documentList = search.GetNextSet();
        Console.WriteLine("\nFindRepliesPostedWithinTimePeriod: printing replies posted within dates: {0} and {1} ............", startDate, endDate);
        foreach (var document in documentList)
        {
          PrintDocument(document);
        }
      } while (!search.IsDone);
    }

    private static void FindRepliesInLast15DaysWithConfig(Table table, string forumName, string threadName)
    {
      DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);
      QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#" + threadName);
      filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan, twoWeeksAgoDate);
      // You are specifying optional parameters so use QueryOperationConfig.
      QueryOperationConfig config = new QueryOperationConfig()
      {
        Filter = filter,
        // Optional parameters.
        Select = SelectValues.SpecificAttributes,
        AttributesToGet = new List<string> { "Message", "ReplyDateTime", 
                                             "PostedBy" },
        ConsistentRead = true
      };

      Search search = table.Query(config);

      List<Document> documentSet = new List<Document>();
      do
      {
        documentSet = search.GetNextSet();
        Console.WriteLine("\nFindRepliesInLast15DaysWithConfig: printing ............");
        foreach (var document in documentSet)
          PrintDocument(document);
      } while (!search.IsDone);
    }

    private static void PrintDocument(Document document)
    {
      //   count++;
      Console.WriteLine();
      foreach (var attribute in document.GetAttributeNames())
      {
        string stringValue = null;
        var value = document[attribute];
        if (value is Primitive)
          stringValue = value.AsPrimitive().Value.ToString();
        else if (value is PrimitiveList)
          stringValue = string.Join(",", (from primitive
                                            in value.AsPrimitiveList().Entries
                                          select primitive.Value).ToArray());
        Console.WriteLine("{0} - {1}", attribute, stringValue);
      }
    }
  }
}