

# 处理全局二级索引：.NET
<a name="GSILowLevelDotNet"></a>

您可以使用 适用于 .NET 的 AWS SDK 低级 API 创建具有一个或多个全局二级索引的 Amazon DynamoDB 表、描述表中的索引，以及使用索引执行查询。这些操作映射到对应的 DynamoDB 操作。有关更多信息，请参阅 [Amazon DynamoDB API 参考](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/)。

以下是使用 .NET 低级 API 执行表操作的常见步骤。

1. 创建 `AmazonDynamoDBClient` 类的实例。

1. 通过创建对应的请求对象，为操作提供必需参数和可选参数。

   例如，创建一个 `CreateTableRequest` 对象以创建表；创建一个 `QueryRequest` 数据元以查询表或索引。

1. 执行您在前面步骤中创建的客户端提供的适当方法。

**Topics**
+ [创建一个具有全局二级索引的表。](#GSILowLevelDotNet.CreateTableWithIndex)
+ [描述一个具有全局二级索引的表](#GSILowLevelDotNet.DescribeTableWithIndex)
+ [查询全局二级索引](#GSILowLevelDotNet.QueryAnIndex)
+ [示例：使用 适用于 .NET 的 AWS SDK 低级 API 的全局二级索引](GSILowLevelDotNet.Example.md)

## 创建一个具有全局二级索引的表。
<a name="GSILowLevelDotNet.CreateTableWithIndex"></a>

创建表时可以同时创建全局二级索引。为此，请使用 `CreateTable` 并为一个或多个全局二级索引提供您的规范。以下 C\$1 代码示例创建一个保存天气数据信息的表。分区键为 `Location`，排序键为 `Date`。全局二级索引 `PrecipIndex` 允许快速访问各个位置的降水数据。

以下是使用 .NET 低级别 API 创建具有全局二级索引的表的步骤。

1. 创建 `AmazonDynamoDBClient` 类的实例。

1. 创建 `CreateTableRequest` 类实例，以提供请求信息。

   您必须提供表名称、主键以及预配置吞吐量值。对于全局二级索引，您必须提供索引名称、其预置的吞吐量设置、索引排序键的属性定义、索引的键架构以及属性投影。

1. 以参数形式提供请求对象，运行 `CreateTable` 方法。

以下 C\$1 代码示例演示了上述步骤。创建具有全局二级索引 (`PrecipIndex`) 的表 (`WeatherData`)。索引分区键为 `Date`，排序键为 `Precipitation`。所有表属性都投影到索引中。用户可以查询此索引以获取特定日期的天气数据，也可以选择按降水量对数据进行排序。

由于 `Precipitation` 不是表的键属性，它不是必需的。然而,`WeatherData` 项目不包含 `Precipitation`，不会显示在 `PrecipIndex` 中。

```
client = new AmazonDynamoDBClient();
string tableName = "WeatherData";

// Attribute definitions
var attributeDefinitions = new List<AttributeDefinition>()
{
    {new AttributeDefinition{
        AttributeName = "Location",
        AttributeType = "S"}},
    {new AttributeDefinition{
        AttributeName = "Date",
        AttributeType = "S"}},
    {new AttributeDefinition(){
        AttributeName = "Precipitation",
        AttributeType = "N"}
    }
};

// Table key schema
var tableKeySchema = new List<KeySchemaElement>()
{
    {new KeySchemaElement {
        AttributeName = "Location",
        KeyType = "HASH"}},  //Partition key
    {new KeySchemaElement {
        AttributeName = "Date",
        KeyType = "RANGE"}  //Sort key
    }
};

// PrecipIndex
var precipIndex = new GlobalSecondaryIndex
{
    IndexName = "PrecipIndex",
    ProvisionedThroughput = new ProvisionedThroughput
    {
        ReadCapacityUnits = (long)10,
        WriteCapacityUnits = (long)1
    },
    Projection = new Projection { ProjectionType = "ALL" }
};

var indexKeySchema = new List<KeySchemaElement> {
    {new KeySchemaElement { AttributeName = "Date", KeyType = "HASH"}},  //Partition key
    {new KeySchemaElement{AttributeName = "Precipitation",KeyType = "RANGE"}}  //Sort key
};

precipIndex.KeySchema = indexKeySchema;

CreateTableRequest createTableRequest = new CreateTableRequest
{
    TableName = tableName,
    ProvisionedThroughput = new ProvisionedThroughput
    {
        ReadCapacityUnits = (long)5,
        WriteCapacityUnits = (long)1
    },
    AttributeDefinitions = attributeDefinitions,
    KeySchema = tableKeySchema,
    GlobalSecondaryIndexes = { precipIndex }
};

CreateTableResponse response = client.CreateTable(createTableRequest);
Console.WriteLine(response.CreateTableResult.TableDescription.TableName);
Console.WriteLine(response.CreateTableResult.TableDescription.TableStatus);
```

您必须等待 DynamoDB 创建该表并将表的状态设置为 `ACTIVE`。然后，您就可以开始在表中添加数据项目。

## 描述一个具有全局二级索引的表
<a name="GSILowLevelDotNet.DescribeTableWithIndex"></a>

要获取表上全局二级索引的信息，请使用 `DescribeTable`。对于每个索引，您都可以查看其名称、键架构和投影的属性。

以下介绍使用 .NET 低级 API 访问表中全局二级索引信息的步骤。

1. 创建 `AmazonDynamoDBClient` 类的实例。

1. 以参数形式提供请求对象，运行 `describeTable` 方法。

   创建 `DescribeTableRequest` 类实例，以提供请求信息。您必须提供表名称。

以下 C\$1 代码示例演示了上述步骤。

**Example**  

```
client = new AmazonDynamoDBClient();
string tableName = "WeatherData";

DescribeTableResponse response = client.DescribeTable(new DescribeTableRequest { TableName = tableName});

List<GlobalSecondaryIndexDescription> globalSecondaryIndexes =
response.DescribeTableResult.Table.GlobalSecondaryIndexes;

// This code snippet will work for multiple indexes, even though
// there is only one index in this example.

foreach (GlobalSecondaryIndexDescription gsiDescription in globalSecondaryIndexes) {
     Console.WriteLine("Info for index " + gsiDescription.IndexName + ":");

     foreach (KeySchemaElement kse in gsiDescription.KeySchema) {
          Console.WriteLine("\t" + kse.AttributeName + ": key type is " + kse.KeyType);
     }

      Projection projection = gsiDescription.Projection;
      Console.WriteLine("\tThe projection type is: " + projection.ProjectionType);

      if (projection.ProjectionType.ToString().Equals("INCLUDE")) {
           Console.WriteLine("\t\tThe non-key projected attributes are: "
                + projection.NonKeyAttributes);
      }
}
```

## 查询全局二级索引
<a name="GSILowLevelDotNet.QueryAnIndex"></a>

您可以对全局二级索引使用 `Query`，基本上与对表执行 `Query` 操作相同。您需要指定索引名称、索引分区键和排序键（如果有）的查询条件以及要返回的属性。在本示例中，索引是 `PrecipIndex`，其分区键为 `Date`，排序键 `Precipitation`。索引查询返回特定日期降水量大于零的所有天气数据。

以下是使用 .NET 低级别 API 查询全局二级索引的步骤。

1. 创建 `AmazonDynamoDBClient` 类的实例。

1. 创建 `QueryRequest` 类实例，以提供请求信息。

1. 以参数形式提供请求对象，运行 `query` 方法。

属性名称 `Date` 是 DynamoDB 保留关键字。因此，您必须将表达式属性名称用作 `KeyConditionExpression` 的占位符。

以下 C\$1 代码示例演示了上述步骤。

**Example**  

```
client = new AmazonDynamoDBClient();

QueryRequest queryRequest = new QueryRequest
{
    TableName = "WeatherData",
    IndexName = "PrecipIndex",
    KeyConditionExpression = "#dt = :v_date and Precipitation > :v_precip",
    ExpressionAttributeNames = new Dictionary<String, String> {
        {"#dt", "Date"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
        {":v_date", new AttributeValue { S =  "2013-08-01" }},
        {":v_precip", new AttributeValue { N =  "0" }}
    },
    ScanIndexForward = true
};

var result = client.Query(queryRequest);

var items = result.Items;
foreach (var currentItem in items)
{
    foreach (string attr in currentItem.Keys)
    {
        Console.Write(attr + "---> ");
        if (attr == "Precipitation")
        {
            Console.WriteLine(currentItem[attr].N);
    }
    else
    {
        Console.WriteLine(currentItem[attr].S);
    }

         }
     Console.WriteLine();
}
```