Dalam modul ini, Anda akan mempelajari beberapa contoh sederhana mengambil beberapa item dalam satu panggilan API dengan DynamoDB. Anda juga akan belajar tentang cara menggunakan indeks sekunder untuk mengaktifkan pola query tambahan pada tabel DynamoDB Anda.

Waktu untuk Menyelesaikan Modul: 15 Menit


Dalam Modul 2, Anda melihat cara mengambil satu buku dari tabel DynamoDB dengan menggunakan panggilan API GetItem. Pola akses ini berguna, tetapi aplikasi Anda juga harus dapat mengambil beberapa item dalam satu panggilan. Misalnya, Anda mungkin ingin mengambil semua buku karya John Grisham sehingga Anda dapat menampilkannya kepada pengguna. Pada Langkah 1 dalam modul ini, Anda menggunakan API Query untuk mengambil semua buku karya penulis tertentu.

Panggilan API GetItem untuk mengambil satu buku dan panggilan API Query untuk mengambil semua buku karya penulis tertentu sama-sama menggunakan primary key yang ditentukan pada tabel Books Anda. Namun, Anda sebaiknya mengaktifkan pola akses lainnya, seperti mengambil semua buku kategori tertentu seperti sejarah atau biografi. Category bukan bagian dari primary key tabel Anda, tetapi Anda dapat membuat indeks sekunder untuk menambah pola akses lainnya. Anda akan membuat indeks sekunder dan meminta indeks sekunder dalam Langkah 2 dan 3 dari modul ini.


  • Langkah 1. Mengambil beberapa item dengan query

    Bila tabel Anda menggunakan primary key komposit, Anda bisa mengambil semua item dengan hash key yang sama dengan menggunakan panggilan API Query. Untuk aplikasi Anda, ini artinya Anda dapat mengambil semua buku dengan atribut Author yang sama.

    Di terminal AWS Cloud9, jalankan perintah berikut.

    $ python query_items.py

    Perintah ini menjalankan skrip berikut yang mengambil semua buku karya John Grisham.

    import boto3
    from boto3.dynamodb.conditions import Key
    
    # boto3 is the AWS SDK library for Python.
    # The "resources" interface allows for a higher-level abstraction than the low-level client interface.
    # For more details, go to http://boto3.readthedocs.io/en/latest/guide/resources.html
    dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
    table = dynamodb.Table('Books')
    
    # When making a Query API call, you use the KeyConditionExpression parameter to specify the hash key on which you want to query.
    # You’re using the Key object from the Boto 3 library to specify that you want the attribute name ("Author")
    # to equal "John Grisham" by using the ".eq()" method.
    resp = table.query(KeyConditionExpression=Key('Author').eq('John Grisham'))
    
    print("The query returned the following items:")
    for item in resp['Items']:
        print(item)

    Setelah Anda menjalankan skrip, Anda akan melihat dua buku John Grisham, The Firm dan The Rainmaker.

    $ python query_items.py
    The query returned the following items:
    {'Title': 'The Firm', 'Formats': {'Hardcover': 'Q7QWE3U2', 'Paperback': 'ZVZAYY4F', 'Audiobook': 'DJ9KS9NM'}, 'Author': 'John Grisham', 'Category': 'Suspense'}
    {'Title': 'The Rainmaker', 'Formats': {'Hardcover': 'J4SUKVGU', 'Paperback': 'D7YF4FCX'}, 'Author': 'John Grisham', 'Category': 'Suspense'}

    Mengambil beberapa item dengan satu panggilan di DynamoDB adalah pola umum dan mudah dilakukan dengan panggilan API Query .

  • Langkah 2. Membuat indeks sekunder

    Dengan DynamoDB Anda dapat membuat indeks sekunder untuk menjadi pola akses data tambahan di tabel Anda. Indeks sekunder menjadi cara ampuh untuk melengkapi fleksibilitas query pada tabel DynamoDB.

    DynamoDB memiliki dua jenis indeks sekunder: indeks sekunder global dan indeks sekunder lokal. Di bagian ini, indeks sekunder global ditambahkan ke atribut Kategori Anda sehingga Anda akan dapat mengambil semua buku dalam kategori tertentu.

    Contoh skrip berikut menambahkan indeks sekunder global ke tabel yang ada.

    import boto3
    
    # Boto3 is the AWS SDK library for Python.
    # You can use the low-level client to make API calls to DynamoDB.
    client = boto3.client('dynamodb', region_name='us-east-1')
    
    try:
        resp = client.update_table(
            TableName="Books",
            # Any attributes used in your new global secondary index must be declared in AttributeDefinitions
            AttributeDefinitions=[
                {
                    "AttributeName": "Category",
                    "AttributeType": "S"
                },
            ],
            # This is where you add, update, or delete any global secondary indexes on your table.
            GlobalSecondaryIndexUpdates=[
                {
                    "Create": {
                        # You need to name your index and specifically refer to it when using it for queries.
                        "IndexName": "CategoryIndex",
                        # Like the table itself, you need to specify the key schema for an index.
                        # For a global secondary index, you can use a simple or composite key schema.
                        "KeySchema": [
                            {
                                "AttributeName": "Category",
                                "KeyType": "HASH"
                            }
                        ],
                        # You can choose to copy only specific attributes from the original item into the index.
                        # You might want to copy only a few attributes to save space.
                        "Projection": {
                            "ProjectionType": "ALL"
                        },
                        # Global secondary indexes have read and write capacity separate from the underlying table.
                        "ProvisionedThroughput": {
                            "ReadCapacityUnits": 1,
                            "WriteCapacityUnits": 1,
                        }
                    }
                }
            ],
        )
        print("Secondary index added!")
    except Exception as e:
        print("Error updating table:")
        print(e)

    Membuat indeks sekunder global memiliki banyak kesamaan dengan membuat tabel. Anda tentukan nama untuk indeks, atribut yang akan berada di indeks, skema kunci indeks, dan throughput yang disediakan (kapasitas maksimum yang dapat dipakai aplikasi dari suatu tabel atau indeks). Throughput yang disediakan di tiap indeks berbeda dengan throughput yang disediakan di suatu tabel. Sehingga Anda dapat menentukan throughput secara granular untuk memenuhi kebutuhan aplikasi Anda.

    Jalankan perintah berikut di terminal Anda untuk menambahkan indeks sekunder global Anda.

    $ python add_secondary_index.py

    Skrip ini menambahkan indeks sekunder global yang disebut CategoryIndex pada tabel Books Anda.

  • Langkah 3. Query indeks sekunder

    Setelah memiliki CategoryIndex, Anda bisa menggunakannya untuk mengambil semua buku dengan kategori tertentu. Menggunakan indeks sekunder untuk query tabel hampir sama dengan menggunakan panggilan API Query. Sekarang Anda tambahkan nama indeks pada panggilan API.

    Saat Anda menambahkan indeks sekunder global pada tabel yang ada, DynamoDB secara asinkron mengisi balik indeks dengan item-item yang ada dalam tabel. Indeks akan siap untuk query setelah semua item diisikan kembali. Waktu pengisian balik bervariasi sesuai ukuran tabel.

    Anda bisa gunakan skrip query_with_index.py untuk query terhadap indeks baru. Jalankan skrip di terminal Anda dengan perintah berikut.

    $ python query_with_index.py

    Perintah ini menjalankan skrip berikut untuk mengambil semua buku di toko dengan Category Suspense.

    import time
    
    import boto3
    from boto3.dynamodb.conditions import Key
    
    # Boto3 is the AWS SDK library for Python.
    # The "resources" interface allows for a higher-level abstraction than the low-level client interface.
    # For more details, go to http://boto3.readthedocs.io/en/latest/guide/resources.html
    dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
    table = dynamodb.Table('Books')
    
    # When adding a global secondary index to an existing table, you cannot query the index until it has been backfilled.
    # This portion of the script waits until the index is in the “ACTIVE” status, indicating it is ready to be queried.
    while True:
        if not table.global_secondary_indexes or table.global_secondary_indexes[0]['IndexStatus'] != 'ACTIVE':
            print('Waiting for index to backfill...')
            time.sleep(5)
            table.reload()
        else:
            break
    
    # When making a Query call, you use the KeyConditionExpression parameter to specify the hash key on which you want to query.
    # If you want to use a specific index, you also need to pass the IndexName in our API call.
    resp = table.query(
        # Add the name of the index you want to use in your query.
        IndexName="CategoryIndex",
        KeyConditionExpression=Key('Category').eq('Suspense'),
    )
    
    print("The query returned the following items:")
    for item in resp['Items']:
        print(item)

    Perhatikan bahwa ada sebagian skrip yang menunggu hingga indeks siap untuk query.

    Anda akan melihat output berikut di terminal Anda.

    $ python query_with_index.py
    The query returned the following items:
    {'Title': 'The Firm', 'Formats': {'Hardcover': 'Q7QWE3U2', 'Paperback': 'ZVZAYY4F', 'Audiobook': 'DJ9KS9NM'}, 'Author': 'John Grisham', 'Category': 'Suspense'}
    {'Title': 'The Rainmaker', 'Formats': {'Hardcover': 'J4SUKVGU', 'Paperback': 'D7YF4FCX'}, 'Author': 'John Grisham', 'Category': 'Suspense'}
    {'Title': 'Along Came a Spider', 'Formats': {'Hardcover': 'C9NR6RJ7', 'Paperback': '37JVGDZG', 'Audiobook': '6348WX3U'}, 'Author': 'James Patterson', 'Category': 'Suspense'}

    Query mengembalikan tiga buku karya dua penulis berbeda. Ini adalah pola query yang sedianya akan sulit dengan skema primary key tabel Anda tetapi mudah diimplementasikan dengan kekuatan indeks sekunder.


    Pada modul berikutnya, Anda akan belajar cara memperbarui atribut item yang ada di suatu tabel dengan menggunakan API UpdateItem