

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Gunakan indeks sekunder
<a name="ddb-en-client-use-secindex"></a>

[Kunci utama](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean) tabel mendefinisikan indeks utama, yang menentukan bagaimana DynamoDB menyimpan dan mengambil item secara default. 

Indeks sekunder menyediakan kunci alternatif yang Anda gunakan dalam operasi kueri dan pemindaian. Indeks sekunder global (GSI) memiliki kunci partisi dan kunci pengurutan opsional yang dapat berbeda dari yang ada di tabel dasar. Sebaliknya, indeks sekunder lokal (LSI) berbagi kunci partisi dari indeks primer tetapi menentukan kunci pengurutan yang berbeda.

## Tentukan kunci untuk indeks sekunder global dan lokal
<a name="ddb-en-client-use-secindex-annomodel"></a>

Atribut yang berpartisipasi dalam indeks sekunder memerlukan `@DynamoDbSecondarySortKey` anotasi `@DynamoDbSecondaryPartitionKey` atau anotasi.

Kelas berikut menunjukkan anotasi untuk dua indeks. GSI bernama *SubjectLastPostedDateIndex*menggunakan `Subject` atribut untuk kunci partisi dan `LastPostedDateTime` untuk kunci sortir. LSI bernama *ForumLastPostedDateIndex*menggunakan `ForumName` sebagai kunci partisi dan `LastPostedDateTime` sebagai kunci sortir.

Perhatikan bahwa `Subject` atribut tersebut memiliki peran ganda. Ini adalah kunci sortir kunci primer dan kunci partisi dari GSI bernama *SubjectLastPostedDateIndex*.

### `MessageThread` kelas
<a name="ddb-en-client-use-secindex-class"></a>

`MessageThread`Kelas ini cocok untuk digunakan sebagai kelas data untuk [tabel Thread contoh](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AppendixSampleTables.html) di *Amazon DynamoDB* Developer Guide.

#### Impor
<a name="ddb-en-client-use-secindex-classimports"></a>

```
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.util.List;
```

```
@DynamoDbBean
public class MessageThread {
    private String ForumName;
    private String Subject;
    private String Message;
    private String LastPostedBy;
    private String LastPostedDateTime;
    private Integer Views;
    private Integer Replies;
    private Integer Answered;
    private List<String> Tags;

    @DynamoDbPartitionKey
    public String getForumName() {
        return ForumName;
    }

    public void setForumName(String forumName) {
        ForumName = forumName;
    }

    // Sort key for primary index and partition key for GSI "SubjectLastPostedDateIndex".
    @DynamoDbSortKey
    @DynamoDbSecondaryPartitionKey(indexNames = "SubjectLastPostedDateIndex")
    public String getSubject() {
        return Subject;
    }

    public void setSubject(String subject) {
        Subject = subject;
    }

    // Sort key for GSI "SubjectLastPostedDateIndex" and sort key for LSI "ForumLastPostedDateIndex".
    @DynamoDbSecondarySortKey(indexNames = {"SubjectLastPostedDateIndex", "ForumLastPostedDateIndex"})
    public String getLastPostedDateTime() {
        return LastPostedDateTime;
    }

    public void setLastPostedDateTime(String lastPostedDateTime) {
        LastPostedDateTime = lastPostedDateTime;
    }
    public String getMessage() {
        return Message;
    }

    public void setMessage(String message) {
        Message = message;
    }

    public String getLastPostedBy() {
        return LastPostedBy;
    }

    public void setLastPostedBy(String lastPostedBy) {
        LastPostedBy = lastPostedBy;
    }

    public Integer getViews() {
        return Views;
    }

    public void setViews(Integer views) {
        Views = views;
    }

    @DynamoDbSecondaryPartitionKey(indexNames = "ForumRepliesIndex")
    public Integer getReplies() {
        return Replies;
    }

    public void setReplies(Integer replies) {
        Replies = replies;
    }

    public Integer getAnswered() {
        return Answered;
    }

    public void setAnswered(Integer answered) {
        Answered = answered;
    }

    public List<String> getTags() {
        return Tags;
    }

    public void setTags(List<String> tags) {
        Tags = tags;
    }

    public MessageThread() {
        this.Answered = 0;
        this.LastPostedBy = "";
        this.ForumName = "";
        this.Message = "";
        this.LastPostedDateTime = "";
        this.Replies = 0;
        this.Views = 0;
        this.Subject = "";
    }

    @Override
    public String toString() {
        return "MessageThread{" +
                "ForumName='" + ForumName + '\'' +
                ", Subject='" + Subject + '\'' +
                ", Message='" + Message + '\'' +
                ", LastPostedBy='" + LastPostedBy + '\'' +
                ", LastPostedDateTime='" + LastPostedDateTime + '\'' +
                ", Views=" + Views +
                ", Replies=" + Replies +
                ", Answered=" + Answered +
                ", Tags=" + Tags +
                '}';
    }
}
```

## Buat indeks
<a name="ddb-en-client-use-secindex-confindex"></a>

Dimulai dengan versi 2.20.86 SDK for Java, `createTable()` metode ini secara otomatis menghasilkan indeks sekunder dari anotasi kelas data. Secara default, semua atribut dari tabel dasar disalin ke indeks dan nilai throughput yang disediakan adalah 20 unit kapasitas baca dan 20 unit kapasitas tulis.

Namun, jika Anda menggunakan versi SDK sebelum 2.20.86, Anda perlu membuat indeks bersama dengan tabel seperti yang ditunjukkan pada contoh berikut. Contoh ini membangun dua indeks untuk tabel. `Thread` Parameter [builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html) memiliki metode untuk mengkonfigurasi kedua jenis indeks seperti yang ditunjukkan setelah baris komentar 1 dan 2. Anda menggunakan `indexName()` metode pembuat indeks untuk mengaitkan nama indeks yang ditentukan dalam anotasi kelas data dengan jenis indeks yang dimaksud.

Kode ini mengkonfigurasi semua atribut tabel untuk berakhir di kedua indeks setelah baris komentar 3 dan 4. Informasi selengkapnya tentang [proyeksi atribut](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.Projections) tersedia di Panduan Pengembang *Amazon DynamoDB*.

```
    public static void createMessageThreadTable(DynamoDbTable<MessageThread> messageThreadDynamoDbTable, DynamoDbClient dynamoDbClient) {
        messageThreadDynamoDbTable.createTable(b -> b
                // 1. Generate the GSI.
                .globalSecondaryIndices(gsi -> gsi.indexName("SubjectLastPostedDateIndex")
                        // 3. Populate the GSI with all attributes.
                        .projection(p -> p
                                .projectionType(ProjectionType.ALL))
                )
                // 2. Generate the LSI.
                .localSecondaryIndices(lsi -> lsi.indexName("ForumLastPostedDateIndex")
                        // 4. Populate the LSI with all attributes.
                        .projection(p -> p
                                .projectionType(ProjectionType.ALL))
                )
        );
```

## Kueri dengan menggunakan indeks
<a name="ddb-en-client-use-secindex-query"></a>

Contoh berikut query indeks *ForumLastPostedDateIndex*sekunder lokal.

Mengikuti baris komentar 2, Anda membuat [QueryConditional](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)objek yang diperlukan saat memanggil metode [DynamoDbIndex.query()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbIndex.html#query(java.util.function.Consumer)). 

Anda mendapatkan referensi ke indeks yang ingin Anda kueri setelah baris komentar 3 dengan meneruskan nama indeks. Mengikuti baris komentar 4, Anda memanggil `query()` metode pada indeks yang lewat di `QueryConditional` objek. 

Anda juga mengonfigurasi kueri untuk mengembalikan tiga nilai atribut seperti yang ditunjukkan setelah baris komentar 5. Jika tidak `attributesToProject()` dipanggil, query mengembalikan semua nilai atribut. Perhatikan bahwa nama atribut yang ditentukan dimulai dengan huruf kecil. Nama atribut ini cocok dengan yang digunakan dalam tabel, belum tentu nama atribut dari kelas data.

Mengikuti baris komentar 6, ulangi hasil dan log setiap item yang dikembalikan oleh kueri dan juga menyimpannya dalam daftar untuk kembali ke pemanggil.

```
public class IndexScanExamples {
    private static Logger logger = LoggerFactory.getLogger(IndexScanExamples.class);

    public static List<MessageThread> queryUsingSecondaryIndices(String lastPostedDate,
                                                                 DynamoDbTable<MessageThread> threadTable) {
        // 1. Log the parameter value.
        logger.info("lastPostedDate value: {}", lastPostedDate);

        // 2. Create a QueryConditional whose sort key value must be greater than or equal to the parameter value.
        QueryConditional queryConditional = QueryConditional.sortGreaterThanOrEqualTo(qc ->
                qc.partitionValue("Forum02").sortValue(lastPostedDate));

        // 3. Specify the index name to query.
        final DynamoDbIndex<MessageThread> forumLastPostedDateIndex = threadTable.index("ForumLastPostedDateIndex");

        // 4. Perform the query using the QueryConditional object.
        final SdkIterable<Page<MessageThread>> pagedResult = forumLastPostedDateIndex.query(q -> q
                .queryConditional(queryConditional)
                // 5. Request three attribute in the results.
                .attributesToProject("forumName", "subject", "lastPostedDateTime"));

        List<MessageThread> collectedItems = new ArrayList<>();
        // 6. Iterate through pages response and sort the items.
        pagedResult.stream().forEach(page -> page.items().stream()
                .sorted(Comparator.comparing(MessageThread::getLastPostedDateTime))
                .forEach(mt -> {
                    // 7. Log the returned items and add the collection to return to the caller.
                    logger.info(mt.toString());
                    collectedItems.add(mt);
                }));
        return collectedItems;
    }
```

Item berikut ada dalam database sebelum query dijalankan.

```
MessageThread{ForumName='Forum01', Subject='Subject01', Message='Message01', LastPostedBy='', LastPostedDateTime='2023.03.28', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject02', Message='Message02', LastPostedBy='', LastPostedDateTime='2023.03.29', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject04', Message='Message04', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject08', Message='Message08', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject10', Message='Message10', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject03', Message='Message03', LastPostedBy='', LastPostedDateTime='2023.03.30', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject06', Message='Message06', LastPostedBy='', LastPostedDateTime='2023.04.02', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject09', Message='Message09', LastPostedBy='', LastPostedDateTime='2023.04.05', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum05', Subject='Subject05', Message='Message05', LastPostedBy='', LastPostedDateTime='2023.04.01', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum07', Subject='Subject07', Message='Message07', LastPostedBy='', LastPostedDateTime='2023.04.03', Views=0, Replies=0, Answered=0, Tags=null}
```

Pernyataan logging pada baris 1 dan 6 menghasilkan output konsol berikut.

```
lastPostedDate value: 2023.03.31
MessageThread{ForumName='Forum02', Subject='Subject04', Message='', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject08', Message='', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject10', Message='', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}
```

*Kueri mengembalikan item dengan `forumName` nilai *Forum02* dan `lastPostedDateTime` nilai lebih besar dari atau sama dengan 2023.03.31.* Hasilnya menunjukkan `message` nilai dengan string kosong meskipun `message` atribut memiliki nilai dalam indeks. Ini karena atribut pesan tidak diproyeksikan oleh kode setelah baris komentar 5. 

## Gunakan kunci komposit untuk indeks sekunder global (GSI)
<a name="ddb-en-client-use-secindex-composite"></a>

SDK for Java 2.x DynamoDB Enhanced Client mendukung kunci komposit untuk indeks sekunder global. Anda dapat menentukan hingga empat atribut kunci partisi dan empat atribut kunci pengurutan untuk GSI tunggal. Ini menghilangkan kebutuhan untuk menggabungkan beberapa atribut menjadi satu kunci string di sisi klien.

Gunakan `order` parameter pada `@DynamoDbSecondaryPartitionKey` dan `@DynamoDbSecondarySortKey` anotasi untuk menentukan posisi setiap atribut dalam kunci komposit. `order`Parameter menerima nilai dari [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/Order.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/Order.html)enum (bagian dari Enhanced DynamoDB Client):,,, dan. `FIRST` `SECOND` `THIRD` `FOURTH`

### Anotasi kelas data dengan anotasi kunci komposit
<a name="ddb-en-client-use-secindex-composite-anno"></a>

Contoh berikut memodelkan tabel pesanan. Tabel dasar digunakan `orderId` sebagai kunci partisi. GSI bernama *OrdersByStatusDateAmount*menggunakan kunci partisi komposit `customerId` dan`status`, dan kunci sortir komposit dari `orderDate` dan`amount`. Desain ini memungkinkan Anda menanyakan pesanan pelanggan yang difilter berdasarkan status, tanggal, dan ambang batas jumlah.

#### Impor
<a name="ddb-en-client-use-secindex-composite-annoimports"></a>

```
import software.amazon.awssdk.enhanced.dynamodb.mapper.Order;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
```

```
@DynamoDbBean
public class OrderItem {
    private String orderId;
    private String customerId;
    private String status;
    private String orderDate;
    private Integer amount;

    @DynamoDbPartitionKey
    public String getOrderId() {
        return orderId;
    }
    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    // First partition key attribute for the GSI.
    @DynamoDbSecondaryPartitionKey(indexNames = "OrdersByStatusDateAmount", order = Order.FIRST)
    public String getCustomerId() {
        return customerId;
    }
    public void setCustomerId(String customerId) {
        this.customerId = customerId;
    }

    // Second partition key attribute for the GSI.
    @DynamoDbSecondaryPartitionKey(indexNames = "OrdersByStatusDateAmount", order = Order.SECOND)
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }

    // First sort key attribute for the GSI.
    @DynamoDbSecondarySortKey(indexNames = "OrdersByStatusDateAmount", order = Order.FIRST)
    public String getOrderDate() {
        return orderDate;
    }
    public void setOrderDate(String orderDate) {
        this.orderDate = orderDate;
    }

    // Second sort key attribute for the GSI.
    @DynamoDbSecondarySortKey(indexNames = "OrdersByStatusDateAmount", order = Order.SECOND)
    public Integer getAmount() {
        return amount;
    }
    public void setAmount(Integer amount) {
        this.amount = amount;
    }
}
```

### Kueri dengan menggunakan indeks kunci komposit
<a name="ddb-en-client-use-secindex-composite-query"></a>

Saat Anda menanyakan indeks kunci komposit, gunakan `addSortValue()` metode `addPartitionValue()` dan pada pembuat [Key](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Key.html). Tambahkan nilai dalam urutan yang sama dengan `Order` nilai yang ditentukan dalam anotasi. Semua kunci partisi diperlukan. Kunci sortir bersifat opsional dan dapat disediakan dari kiri ke kanan.

Anda membuat [QueryConditional](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)objek untuk menentukan kondisi kueri. Gunakan `keyEqualTo` untuk kecocokan persis, atau kondisi kunci pengurutan seperti`sortGreaterThan`,`sortLessThan`,`sortBetween`, atau`sortBeginsWith`. Kondisi ini berlaku untuk kunci pengurutan terakhir yang Anda berikan.

Contoh berikut menanyakan *OrdersByStatusDateAmount*GSI, secara progresif menambahkan kunci pengurutan untuk mempersempit hasil.

```
DynamoDbIndex<OrderItem> index = orderTable.index("OrdersByStatusDateAmount");

// All PENDING orders for customer-123.
SdkIterable<Page<OrderItem>> allPending = index.query(q -> q
        .queryConditional(QueryConditional.keyEqualTo(k -> k
                .addPartitionValue("customer-123")
                .addPartitionValue("PENDING"))));

// PENDING orders on a specific date.
SdkIterable<Page<OrderItem>> pendingOnDate = index.query(q -> q
        .queryConditional(QueryConditional.keyEqualTo(k -> k
                .addPartitionValue("customer-123")
                .addPartitionValue("PENDING")
                .addSortValue("2025-11-04"))));

// PENDING orders on a specific date with amount greater than 100.
SdkIterable<Page<OrderItem>> filtered = index.query(q -> q
        .queryConditional(QueryConditional.sortGreaterThan(k -> k
                .addPartitionValue("customer-123")
                .addPartitionValue("PENDING")
                .addSortValue("2025-11-04")
                .addSortValue(100))));
```

Untuk informasi selengkapnya, lihat [Multi-key dukungan untuk Indeks Sekunder Global di DynamoDB](https://aws.amazon.com/blogs/database/multi-key-support-for-global-secondary-index-in-amazon-dynamodb/).