

# グローバルセカンダリインデックスの操作: Java
<a name="GSIJavaDocumentAPI"></a>

AWS SDK for Java ドキュメント API を使用して、1 つ以上のグローバルセカンダリインデックスを持つ Amazon DynamoDB テーブルを作成し、テーブルのインデックスを記述し、インデックスを使用してクエリを実行できます。

以下に、テーブルオペレーションの一般的な手順を示します。

1. `DynamoDB` クラスのインスタンスを作成します。

1. 対応するリクエストオブジェクトを作成して、オペレーションについて必要なパラメータとオプションパラメータを入力します。

1. 前のステップで作成したクライアントが提供する適切なメソッドを呼び出します。

**Topics**
+ [グローバルセカンダリインデックスを持つテーブルを作成します](#GSIJavaDocumentAPI.CreateTableWithIndex)
+ [グローバルセカンダリインデックスを持つテーブルの説明](#GSIJavaDocumentAPI.DescribeTableWithIndex)
+ [グローバルセカンダリインデックスのクエリ](#GSIJavaDocumentAPI.QueryAnIndex)
+ [例: AWS SDK for Java ドキュメント API を使用したグローバルセカンダリインデックス](GSIJavaDocumentAPI.Example.md)

## グローバルセカンダリインデックスを持つテーブルを作成します
<a name="GSIJavaDocumentAPI.CreateTableWithIndex"></a>

グローバルセカンダリインデックスは、テーブルの作成と同時に作成できます。これを行うには、`CreateTable` を使用し、1 つ以上のグローバルセカンダリインデックスの仕様を指定します。次の Java コード例では、気象データに関する情報を保持するテーブルを作成しています。パーティションキーは `Location` で、ソートキーは `Date` です。グローバルセカンダリインデックス `PrecipIndex` は、さまざまな場所の降水データへの高速アクセスを可能にします。

DynamoDB ドキュメント API を使用して、グローバルセカンダリインデックスを持つテーブルを作成する手順を次に示します。

1. `DynamoDB` クラスのインスタンスを作成します。

1. リクエスト情報を指定する `CreateTableRequest` クラスのインスタンスを作成します。

   テーブル名、プライマリキー、およびプロビジョニングされたスループット値を指定する必要があります。グローバルセカンダリインデックスの場合は、インデックス名、プロビジョニングされたスループット設定、インデックスソートキーの属性定義、インデックスのキースキーマ、および属性射影を指定する必要があります。

1. リクエストオブジェクトをパラメータとして指定して、`createTable` メソッドを呼び出します。

以下の Java コード例は、前述のステップの例です。このコードは、グローバルセカンダリインデックス (`PrecipIndex`) を持つテーブル (`WeatherData`) を作成します。インデックスパーティションキーは `Date` で、ソートキーは `Precipitation` です。すべてのテーブル属性がインデックスに射影されます。ユーザーは、このインデックスに対するクエリを実行して、特定の日付の気象データを取得できます。必要に応じて、降水量によってデータを並べ替えることもできます。

`Precipitation` はテーブルのキー属性ではないため、必須ではありません。ただし、`Precipitation` のない `WeatherData` 項目は `PrecipIndex` に表示されません。

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

// Attribute definitions
ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();

attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Location")
    .withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Date")
    .withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Precipitation")
    .withAttributeType("N"));

// Table key schema
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
tableKeySchema.add(new KeySchemaElement()
    .withAttributeName("Location")
    .withKeyType(KeyType.HASH));  //Partition key
tableKeySchema.add(new KeySchemaElement()
    .withAttributeName("Date")
    .withKeyType(KeyType.RANGE));  //Sort key

// PrecipIndex
GlobalSecondaryIndex precipIndex = new GlobalSecondaryIndex()
    .withIndexName("PrecipIndex")
    .withProvisionedThroughput(new ProvisionedThroughput()
        .withReadCapacityUnits((long) 10)
        .withWriteCapacityUnits((long) 1))
        .withProjection(new Projection().withProjectionType(ProjectionType.ALL));

ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

indexKeySchema.add(new KeySchemaElement()
    .withAttributeName("Date")
    .withKeyType(KeyType.HASH));  //Partition key
indexKeySchema.add(new KeySchemaElement()
    .withAttributeName("Precipitation")
    .withKeyType(KeyType.RANGE));  //Sort key

precipIndex.setKeySchema(indexKeySchema);

CreateTableRequest createTableRequest = new CreateTableRequest()
    .withTableName("WeatherData")
    .withProvisionedThroughput(new ProvisionedThroughput()
        .withReadCapacityUnits((long) 5)
        .withWriteCapacityUnits((long) 1))
    .withAttributeDefinitions(attributeDefinitions)
    .withKeySchema(tableKeySchema)
    .withGlobalSecondaryIndexes(precipIndex);

Table table = dynamoDB.createTable(createTableRequest);
System.out.println(table.getDescription());
```

DynamoDB がテーブルを作成し、テーブルのステータスを `ACTIVE` に設定するまで待機する必要があります。その後、テーブルへのデータ項目の入力を開始できます。

## グローバルセカンダリインデックスを持つテーブルの説明
<a name="GSIJavaDocumentAPI.DescribeTableWithIndex"></a>

テーブルでグローバルセカンダリインデックスに関する情報を取得するには、`DescribeTable` を使用します。インデックスごとに、名前、キースキーマ、および射影された属性にアクセスできます。

テーブルのグローバルセカンダリインデックス情報にアクセスする手順を次に示します。

1. `DynamoDB` クラスのインスタンスを作成します。

1. 操作対象のインデックスを表すために、`Table` クラスのインスタンスを作成します。

1. `Table` オブジェクトの `describe` メソッドを呼び出します。

以下の Java コード例は、前述のステップの例です。

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("WeatherData");
TableDescription tableDesc = table.describe();
    

Iterator<GlobalSecondaryIndexDescription> gsiIter = tableDesc.getGlobalSecondaryIndexes().iterator();
while (gsiIter.hasNext()) {
    GlobalSecondaryIndexDescription gsiDesc = gsiIter.next();
    System.out.println("Info for index "
         + gsiDesc.getIndexName() + ":");

    Iterator<KeySchemaElement> kseIter = gsiDesc.getKeySchema().iterator();
    while (kseIter.hasNext()) {
        KeySchemaElement kse = kseIter.next();
        System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType());
    }
    Projection projection = gsiDesc.getProjection();
    System.out.println("\tThe projection type is: "
        + projection.getProjectionType());
    if (projection.getProjectionType().toString().equals("INCLUDE")) {
        System.out.println("\t\tThe non-key projected attributes are: "
            + projection.getNonKeyAttributes());
    }
}
```

## グローバルセカンダリインデックスのクエリ
<a name="GSIJavaDocumentAPI.QueryAnIndex"></a>

テーブルに `Query` を実行するのとほぼ同じ方法で、グローバルセカンダリインデックスに対する `Query` を使用することができます。インデックス名、インデックスパーティションキーとソートキー (存在する場合) のクエリ条件、および返す属性を指定する必要があります。この例では、インデックスは `PrecipIndex` で、パーティションキーが `Date` で、ソートキーが `Precipitation` です。このインデックスクエリは、降水量がゼロより大きい特定の日付のすべての気象データを返します。

AWS SDK for Java ドキュメント API を使用してグローバルセカンダリインデックスをクエリする手順を次に示します。

1. `DynamoDB` クラスのインスタンスを作成します。

1. 操作対象のインデックスを表すために、`Table` クラスのインスタンスを作成します。

1. クエリするインデックスの `Index` クラスのインスタンスを作成します。

1. `Index` オブジェクトの `query` メソッドを呼び出します。

属性名 `Date` は DynamoDB の予約語です。したがって、式の属性名を `KeyConditionExpression` のプレースホルダーとして使用する必要があります。

以下の Java コード例は、前述のステップの例です。

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("WeatherData");
Index index = table.getIndex("PrecipIndex");

QuerySpec spec = new QuerySpec()
    .withKeyConditionExpression("#d = :v_date and Precipitation = :v_precip")
    .withNameMap(new NameMap()
        .with("#d", "Date"))
    .withValueMap(new ValueMap()
        .withString(":v_date","2013-08-10")
        .withNumber(":v_precip",0));

ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> iter = items.iterator(); 
while (iter.hasNext()) {
    System.out.println(iter.next().toJSONPretty());
}
```