DynamoDB - ดัชนีรองในเครื่อง

แอปพลิเคชันบางตัวดำเนินการสืบค้นด้วยคีย์หลักเท่านั้น แต่บางสถานการณ์จะได้รับประโยชน์จากคีย์การเรียงลำดับสำรอง อนุญาตให้แอปพลิเคชันของคุณเลือกโดยการสร้างดัชนีรองในเครื่องเดียวหรือหลายดัชนี

ข้อกำหนดในการเข้าถึงข้อมูลที่ซับซ้อนเช่นการรวมรายการหลายล้านรายการทำให้จำเป็นต้องดำเนินการสืบค้น / สแกนที่มีประสิทธิภาพมากขึ้น ดัชนีรองในเครื่องมีคีย์การเรียงลำดับสำรองสำหรับค่าคีย์พาร์ติชัน นอกจากนี้ยังมีสำเนาแอตทริบิวต์ของตารางทั้งหมดหรือบางส่วน พวกเขาจัดระเบียบข้อมูลด้วยคีย์พาร์ติชันตาราง แต่ใช้คีย์การจัดเรียงอื่น

การใช้ดัชนีทุติยภูมิในเครื่องจะช่วยขจัดความจำเป็นในการสแกนทั้งตารางและช่วยให้สามารถสืบค้นข้อมูลได้ง่ายและรวดเร็วโดยใช้คีย์การจัดเรียง

ดัชนีทุติยภูมิในพื้นที่ทั้งหมดต้องเป็นไปตามเงื่อนไขบางประการ -

  • คีย์พาร์ติชันที่เหมือนกันและคีย์พาร์ติชันตารางต้นทาง
  • คีย์การจัดเรียงของแอตทริบิวต์สเกลาร์เพียงรายการเดียว
  • การฉายภาพของคีย์การจัดเรียงตารางต้นทางที่ทำหน้าที่เป็นแอตทริบิวต์ที่ไม่ใช่คีย์

ดัชนีรองในเครื่องทั้งหมดจะเก็บคีย์พาร์ติชันและเรียงลำดับจากตารางหลักโดยอัตโนมัติ ในแบบสอบถามหมายถึงการรวบรวมแอตทริบิวต์ที่คาดการณ์ไว้อย่างมีประสิทธิภาพและการดึงข้อมูลแอตทริบิวต์ที่ไม่ได้คาดการณ์ไว้ด้วย

ขีด จำกัด การจัดเก็บสำหรับดัชนีรองภายในเครื่องจะยังคงอยู่ที่ 10GB ต่อค่าคีย์พาร์ติชันซึ่งรวมถึงรายการตารางทั้งหมดและรายการดัชนีที่แชร์ค่าคีย์พาร์ติชัน

การฉายแอททริบิวต์

การดำเนินการบางอย่างต้องการการอ่าน / ดึงข้อมูลส่วนเกินเนื่องจากความซับซ้อน การดำเนินการเหล่านี้สามารถใช้ปริมาณงานได้มาก การฉายภาพช่วยให้คุณหลีกเลี่ยงการดึงข้อมูลที่มีราคาแพงและดำเนินการสืบค้นข้อมูลที่หลากหลายโดยการแยกแอตทริบิวต์เหล่านี้ โปรดจำไว้ว่าการคาดการณ์ประกอบด้วยแอตทริบิวต์ที่คัดลอกไปยังดัชนีรอง

เมื่อสร้างดัชนีรองคุณต้องระบุแอตทริบิวต์ที่คาดการณ์ไว้ เรียกคืนตัวเลือกสามตัวที่มีให้โดย DynamoDB:KEYS_ONLY, INCLUDE, and ALL.

เมื่อเลือกแอตทริบิวต์บางอย่างในการประมาณการให้พิจารณาการแลกเปลี่ยนต้นทุนที่เกี่ยวข้อง -

  • หากคุณคาดการณ์แอตทริบิวต์ที่จำเป็นเพียงเล็กน้อยคุณจะลดต้นทุนการจัดเก็บได้อย่างมาก

  • หากคุณคาดการณ์แอตทริบิวต์ที่ไม่ใช่คีย์ที่เข้าถึงบ่อยคุณจะชดเชยต้นทุนการสแกนด้วยต้นทุนการจัดเก็บ

  • หากคุณฉายแอตทริบิวต์ที่ไม่ใช่คีย์ส่วนใหญ่หรือทั้งหมดสิ่งนี้จะเพิ่มความยืดหยุ่นสูงสุดและลดปริมาณงาน (ไม่มีการดึงข้อมูล) อย่างไรก็ตามต้นทุนการจัดเก็บเพิ่มขึ้น

  • หากคุณคาดการณ์ KEYS_ONLY สำหรับการเขียน / อัปเดตบ่อยครั้งและการสืบค้นที่ไม่บ่อยนักระบบจะย่อขนาดให้เล็กที่สุด แต่ยังคงเตรียมการสืบค้นไว้

การสร้างดัชนีทุติยภูมิในท้องถิ่น

ใช้ LocalSecondaryIndexพารามิเตอร์ของ CreateTable เพื่อสร้างดัชนีรองภายในเครื่องเดียวหรือหลายตัว คุณต้องระบุแอตทริบิวต์ที่ไม่ใช่คีย์หนึ่งรายการสำหรับคีย์การเรียงลำดับ ในการสร้างตารางคุณจะสร้างดัชนีรองในเครื่อง ในการลบคุณจะลบดัชนีเหล่านี้

ตารางที่มีดัชนีรองภายในต้องเป็นไปตามขีด จำกัด ของขนาด 10GB ต่อค่าคีย์พาร์ติชัน แต่สามารถจัดเก็บรายการจำนวนเท่าใดก็ได้

การสืบค้นและการสแกนดัชนีทุติยภูมิในพื้นที่

การดำเนินการเคียวรีบนดัชนีรองภายในจะส่งคืนรายการทั้งหมดที่มีค่าคีย์พาร์ติชันที่ตรงกันเมื่อหลายรายการในดัชนีแบ่งค่าคีย์การเรียงลำดับ รายการที่ตรงกันจะไม่ส่งคืนตามลำดับที่แน่นอน การค้นหาสำหรับดัชนีทุติยภูมิภายในใช้ความสอดคล้องกันในท้ายที่สุดหรืออย่างใดอย่างหนึ่งโดยการอ่านที่สอดคล้องกันอย่างมากจะแสดงค่าล่าสุด

การสแกนจะส่งคืนข้อมูลดัชนีทุติยภูมิในเครื่องทั้งหมด การสแกนกำหนดให้คุณต้องระบุชื่อตารางและดัชนีและอนุญาตให้ใช้นิพจน์ตัวกรองเพื่อทิ้งข้อมูล

การเขียนรายการ

ในการสร้างดัชนีรองในเครื่องคุณต้องระบุแอตทริบิวต์คีย์การเรียงลำดับและประเภทข้อมูล เมื่อคุณเขียนรายการประเภทของรายการจะต้องตรงกับประเภทข้อมูลของคีย์สคีมาหากรายการนั้นกำหนดแอตทริบิวต์ของคีย์ดัชนี

DynamoDB ไม่กำหนดข้อกำหนดความสัมพันธ์แบบหนึ่งต่อหนึ่งบนรายการตารางและรายการดัชนีรองในเครื่อง ตารางที่มีดัชนีทุติยภูมิในเครื่องหลายตัวมีต้นทุนการเขียนสูงกว่าตารางที่มีค่าน้อย

การพิจารณาปริมาณงานในดัชนีทุติยภูมิในท้องถิ่น

การใช้ความจุในการอ่านของแบบสอบถามขึ้นอยู่กับลักษณะของการเข้าถึงข้อมูล ข้อความค้นหาใช้ความสอดคล้องในท้ายที่สุดหรืออย่างใดอย่างหนึ่งโดยมีการอ่านที่สอดคล้องกันอย่างมากโดยใช้หน่วยเดียวเทียบกับครึ่งหน่วยในการอ่านที่สอดคล้องกันในที่สุด

ข้อ จำกัด ของผลลัพธ์รวมถึงขนาดสูงสุด 1MB ขนาดผลลัพธ์มาจากผลรวมของขนาดรายการดัชนีที่ตรงกันปัดเศษขึ้นเป็น 4KB ที่ใกล้ที่สุดและขนาดรายการตารางที่ตรงกันจะปัดเศษเป็น 4KB ที่ใกล้ที่สุด

ปริมาณการใช้ความจุในการเขียนยังคงอยู่ในหน่วยที่จัดเตรียมไว้ คำนวณต้นทุนทั้งหมดที่จัดเตรียมโดยการหาผลรวมของหน่วยบริโภคในการเขียนตารางและหน่วยบริโภคในการอัปเดตดัชนี

คุณยังสามารถพิจารณาปัจจัยสำคัญที่มีผลต่อต้นทุนซึ่งบางส่วน ได้แก่ -

  • เมื่อคุณเขียนรายการที่กำหนดแอตทริบิวต์ที่จัดทำดัชนีหรืออัปเดตรายการเพื่อกำหนดแอตทริบิวต์ที่จัดทำดัชนีที่ไม่ได้กำหนดการดำเนินการเขียนครั้งเดียวจะเกิดขึ้น

  • เมื่อการอัปเดตตารางเปลี่ยนค่าแอตทริบิวต์ของคีย์ที่จัดทำดัชนีการเขียนสองครั้งจะเกิดขึ้นเพื่อลบแล้วเพิ่มรายการ

  • เมื่อการเขียนทำให้เกิดการลบแอตทริบิวต์ที่จัดทำดัชนีการเขียนหนึ่งรายการจะเกิดขึ้นเพื่อลบการคาดการณ์รายการเก่า

  • เมื่อไม่มีรายการอยู่ในดัชนีก่อนหรือหลังการอัพเดตจะไม่มีการเขียนใด ๆ เกิดขึ้น

การจัดเก็บดัชนีทุติยภูมิในเครื่อง

ในการเขียนรายการตาราง DynamoDB จะคัดลอกแอตทริบิวต์ที่เหมาะสมโดยอัตโนมัติไปยังดัชนีรองในเครื่องที่ต้องการ สิ่งนี้เรียกเก็บเงินจากบัญชีของคุณ ช่องว่างที่ใช้เป็นผลมาจากผลรวมของขนาดไบต์ของคีย์หลักของตารางขนาดไบต์แอ็ตทริบิวต์คีย์ดัชนีขนาดไบต์ของแอ็ตทริบิวต์ที่คาดการณ์ไว้ในปัจจุบันและ 100 ไบต์ในค่าโสหุ้ยสำหรับแต่ละรายการดัชนี

การจัดเก็บโดยประมาณได้มาจากการประมาณขนาดรายการดัชนีเฉลี่ยและคูณด้วยปริมาณรายการในตาราง

การใช้ Java เพื่อทำงานกับ Local Secondary Indexes

สร้างดัชนีรองในเครื่องโดยสร้างอินสแตนซ์คลาส DynamoDB ก่อน จากนั้นสร้างอินสแตนซ์คลาส CreateTableRequest พร้อมข้อมูลการร้องขอที่จำเป็น สุดท้ายใช้เมธอด createTable

ตัวอย่าง

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
String tableName = "Tools";  
CreateTableRequest createTableRequest = new 
   CreateTableRequest().withTableName(tableName);
   
//Provisioned Throughput
createTableRequest.setProvisionedThroughput (
   new ProvisionedThroughput()
   .withReadCapacityUnits((long)5)
   .withWriteCapacityUnits(( long)5));
   
//Attributes 
ArrayList<AttributeDefinition> attributeDefinitions = 
   new ArrayList<AttributeDefinition>();
   attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Make")
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Model")
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Line")
   .withAttributeType("S"));
   
createTableRequest.setAttributeDefinitions(attributeDefinitions);

//Key Schema 
ArrayList<KeySchemaElement> tableKeySchema = new 
   ArrayList<KeySchemaElement>();
   
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                    //Partition key
   
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Model")
   .withKeyType(KeyType.RANGE));                   //Sort key
   
createTableRequest.setKeySchema(tableKeySchema);
ArrayList<KeySchemaElement> indexKeySchema = new 
   ArrayList<KeySchemaElement>();
   
indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                   //Partition key
   
indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Line")
   .withKeyType(KeyType.RANGE));                   //Sort key
   
Projection projection = new Projection()
   .withProjectionType(ProjectionType.INCLUDE);

ArrayList<String> nonKeyAttributes = new ArrayList<String>(); 
nonKeyAttributes.add("Type"); 
nonKeyAttributes.add("Year"); 
projection.setNonKeyAttributes(nonKeyAttributes);  

LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex() 
   .withIndexName("ModelIndex")
   .withKeySchema(indexKeySchema)
   .withProjection(p rojection);  

ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new 
   ArrayList<LocalSecondaryIndex>(); 

localSecondaryIndexes.add(localSecondaryIndex); 
createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);  
Table table = dynamoDB.createTable(createTableRequest); 
System.out.println(table.getDescription());

ดึงข้อมูลเกี่ยวกับดัชนีทุติยภูมิภายในด้วยวิธีการอธิบาย เพียงสร้างอินสแตนซ์คลาส DynamoDB สร้างอินสแตนซ์คลาส Table และส่งตารางไปยังเมธอดอธิบาย

ตัวอย่าง

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
   
String tableName = "Tools";
Table table = dynamoDB.getTable(tableName);
TableDescription tableDescription = table.describe();

List<LocalSecondaryIndexDescription> localSecondaryIndexes = 
   tableDescription.getLocalSecondaryIndexes();
   
Iterator<LocalSecondaryIndexDescription> lsiIter = 
   localSecondaryIndexes.iterator();
   
while (lsiIter.hasNext()) {  
   LocalSecondaryIndexDescription lsiDescription = lsiIter.next(); 
   System.out.println("Index info " + lsiDescription.getIndexName() + ":"); 
   Iterator<KeySchemaElement> kseIter = lsiDescription.getKeySchema().iterator(); 
   
   while (kseIter.hasNext()) { 
      KeySchemaElement kse = kseIter.next(); 
      System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType()); 
   }
   
   Projection projection = lsiDescription.getProjection(); 
   System.out.println("\tProjection type: " + projection.getProjectionType()); 
   
   if (projection.getProjectionType().toString().equals("INCLUDE")) { 
      System.out.println("\t\tNon-key projected attributes: " + 
         projection.getNonKeyAttributes()); 
   } 
}

ดำเนินการสืบค้นโดยใช้ขั้นตอนเดียวกับแบบสอบถามตาราง เพียงสร้างอินสแตนซ์คลาส DynamoDB อินสแตนซ์คลาสตารางอินสแตนซ์คลาสดัชนีวัตถุเคียวรีและใช้วิธีเคียวรี

ตัวอย่าง

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
   
String tableName = "Tools";  
Table table = dynamoDB.getTable(tableName); 
Index index = table.getIndex("LineIndex");  
QuerySpec spec = new QuerySpec() 
   .withKeyConditionExpression("Make = :v_make and Line = :v_line") 
   .withValueMap(new ValueMap() 
   .withString(":v_make", "Depault") 
   .withString(":v_line", "SuperSawz"));
      
ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> itemsIter = items.iterator();

while (itemsIter.hasNext()) { 
   Item item = itemsIter.next(); 
   System.out.println(item.toJSONPretty()); 
}

คุณยังสามารถตรวจสอบตัวอย่างต่อไปนี้

Note- ตัวอย่างต่อไปนี้อาจถือว่าเป็นแหล่งข้อมูลที่สร้างขึ้นก่อนหน้านี้ ก่อนที่จะพยายามดำเนินการให้จัดหาไลบรารีที่สนับสนุนและสร้างแหล่งข้อมูลที่จำเป็น (ตารางที่มีคุณสมบัติที่ต้องการหรือแหล่งอ้างอิงอื่น ๆ )

ตัวอย่างต่อไปนี้ยังใช้ Eclipse IDE, ไฟล์หนังสือรับรอง AWS และ AWS Toolkit ภายใน Eclipse AWS Java Project

ตัวอย่าง

import java.util.ArrayList;
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.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.PutItemOutcome;
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;

import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProjectionType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ReturnConsumedCapacity;
import com.amazonaws.services.dynamodbv2.model.Select;

public class LocalSecondaryIndexSample {  
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
      new ProfileCredentialsProvider()));  
   public static String tableName = "ProductOrders";  
   
   public static void main(String[] args) throws Exception {  
      createTable();
      query(null); 
      query("IsOpenIndex"); 
      query("OrderCreationDateIndex"); 
   }
   public static void createTable() { 
      CreateTableRequest createTableRequest = new CreateTableRequest() 
         .withTableName(tableName) 
         .withProvisionedThroughput(new ProvisionedThroughput() 
         .withReadCapacityUnits((long) 1) 
         .withWriteCapacityUnits((long) 1));
         
      // Table partition and sort keys attributes 
      ArrayList<AttributeDefinition> attributeDefinitions = new 
         ArrayList<AttributeDefinition>(); 
      
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("CustomerID") 
         .withAttributeType("S"));
         
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("OrderID") 
         .withAttributeType("N"));
         
      // Index primary key attributes 
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("OrderDate") 
         .withAttributeType("N"));
         
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("OpenStatus") 
         .withAttributeType("N"));  
      createTableRequest.setAttributeDefinitions(attributeDefinitions);
      
      // Table key schema 
      ArrayList<KeySchemaElement> tableKeySchema = new
         ArrayList<KeySchemaElement>(); 
      tableKeySchema.add(new KeySchemaElement()  
         .withAttributeName("CustomerID") 
         .withKeyType(KeyType.HASH));                    //Partition key
         
      tableKeySchema.add(new KeySchemaElement() 
         .withAttributeName("OrderID") 
         .withKeyType(KeyType.RANGE));                   //Sort key
         
      createTableRequest.setKeySchema(tableKeySchema);  
      ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new 
         ArrayList<LocalSecondaryIndex>();  
      
      // OrderDateIndex 
      LocalSecondaryIndex orderDateIndex = new LocalSecondaryIndex() 
         .withIndexName("OrderDateIndex");
         
      // OrderDateIndex key schema 
      ArrayList<KeySchemaElement> indexKeySchema = new 
         ArrayList<KeySchemaElement>(); 
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("CustomerID") 
         .withKeyType(KeyType.HASH));                   //Partition key
         
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("OrderDate") 
         .withKeyType(KeyType.RANGE));                   //Sort key
      orderDateIndex.setKeySchema(indexKeySchema);
      
      // OrderCreationDateIndex projection w/attributes list 
      Projection projection = new Projection() 
         .withProjectionType(ProjectionType.INCLUDE); 
      
      ArrayList<String> nonKeyAttributes = new ArrayList<String>(); 
      nonKeyAttributes.add("ProdCat"); 
      nonKeyAttributes.add("ProdNomenclature"); 
      projection.setNonKeyAttributes(nonKeyAttributes);
      orderCreationDateIndex.setProjection(projection);  
      localSecondaryIndexes.add(orderDateIndex);  
      
      // IsOpenIndex 
      LocalSecondaryIndex isOpenIndex = new LocalSecondaryIndex() 
         .withIndexName("IsOpenIndex");  
      
      // OpenStatusIndex key schema 
      indexKeySchema = new ArrayList<KeySchemaElement>(); 
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("CustomerID") 
         .withKeyType(KeyType.HASH));                   //Partition key
         
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("OpenStatus") 
         .withKeyType(KeyType.RANGE));                   //Sort key
         
      // OpenStatusIndex projection 
      projection = new Projection() .withProjectionType(ProjectionType.ALL);  
      OpenStatusIndex.setKeySchema(indexKeySchema); 
      OpenStatusIndex.setProjection(projection);  
      localSecondaryIndexes.add(OpenStatusIndex);  
      
      // Put definitions in CreateTable request 
      createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);  
      System.out.println("Spawning table " + tableName + "..."); 
      System.out.println(dynamoDB.createTable(createTableRequest));  
      
      // Pause for ACTIVE status 
      System.out.println("Waiting for ACTIVE table:" + tableName); 
      try { 
         Table table = dynamoDB.getTable(tableName);
         table.waitForActive(); 
      } catch (InterruptedException e) { 
         e.printStackTrace(); 
      } 
   }
   public static void query(String indexName) {  
      Table table = dynamoDB.getTable(tableName);  
      System.out.println("\n*************************************************\n"); 
      System.out.println("Executing query on" + tableName);  
      QuerySpec querySpec = new QuerySpec() 
         .withConsistentRead(true) 
         .withScanIndexForward(true) 
         .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);
      
      if (indexName == "OpenStatusIndex") {  
         System.out.println("\nEmploying index: '" + indexName 
            + "' open orders for this customer.");
            
         System.out.println( 
            "Returns only user-specified attribute list\n"); 
         Index index = table.getIndex(indexName); 
             
         querySpec.withKeyConditionExpression("CustomerID = :v_custmid and 
            OpenStatus = :v_openstat") 
            .withValueMap(new ValueMap() 
            .withString(":v_custmid", "[email protected]") 
            .withNumber(":v_openstat", 1));  
         
         querySpec.withProjectionExpression( 
            "OrderDate, ProdCat, ProdNomenclature, OrderStatus"); 
            ItemCollection<QueryOutcome> items = index.query(querySpec); 
            Iterator<Item> iterator = items.iterator();  
            System.out.println("Printing query results...");  
            
         while (iterator.hasNext()) { 
            System.out.println(iterator.next().toJSONPretty()); 
         }  
      } else if (indexName == "OrderDateIndex") { 
         System.out.println("\nUsing index: '" + indexName 
            + "': this customer's orders placed after 05/22/2016."); 
         System.out.println("Projected attributes are returned\n"); 
         Index index = table.getIndex(indexName); 
             
         querySpec.withKeyConditionExpression("CustomerID = :v_custmid and OrderDate 
            >= :v_ordrdate") 
            .withValueMap(new ValueMap() 
            .withString(":v_custmid", "[email protected]") 
            .withNumber(":v_ordrdate", 20160522));
               
         querySpec.withSelect(Select.ALL_PROJECTED_ATTRIBUTES);  
         ItemCollection<QueryOutcome> items = index.query(querySpec); 
         Iterator<Item> iterator = items.iterator();  
         System.out.println("Printing query results...");  
            
         while (iterator.hasNext()) { 
            System.out.println(iterator.next().toJSONPretty()); 
         }  
      } else { 
         System.out.println("\nNo index: All Jane's orders by OrderID:\n"); 
         querySpec.withKeyConditionExpression("CustomerID = :v_custmid") 
            .withValueMap(new ValueMap()
            .withString(":v_custmid", "[email protected]"));  
         
         ItemCollection<QueryOutcome> items = table.query(querySpec); 
         Iterator<Item> iterator = items.iterator();  
         System.out.println("Printing query results...");  
         
         while (iterator.hasNext()) { 
            System.out.println(iterator.next().toJSONPretty()); 
         } 
      } 
   } 
}