Di modul sebelumnya, Anda mengatur akses ke entitas inti Anda di DynamoDB. Struktur kunci utama menyelesaikan sejumlah pola akses utama kita. Termasuk semua pola untuk membaca atau menulis satu entitas, serta pola untuk mengambil beberapa entitas terkait, seperti semua foto milik pengguna tertentu.

Di modul ini, Anda akan mempelajari penggunaan indeks inversi, pola desain umum untuk DynamoDB.

Indeks sekunder adalah alat pemodelan data yang sangat penting dalam DynamoDB. Indeks sekunder memungkinkan Anda membentuk kembali data Anda sebagai pola kueri alternatif.

Indeks inversi adalah pola desain indeks sekunder umum dengan DynamoDB. Dengan indeks inversi, Anda membuat indeks sekunder yang merupakan inversi kunci utama tabel Anda. Kunci HASH untuk tabel Anda menjadi kunci RANGE di indeks, dan kunci RANGE untuk tabel Anda menjadi kunci utama untuk indeks.

Indeks inversi berguna dalam dua skenario. Pertama, indeks inversi berguna untuk kueri sisi “lain” dari hubungan banyak-ke-banyak. Ini adalah kasus untuk entitas Pertemanan . Dengan struktur kunci utama, Anda dapat membuat kueri pada semua pengikut untuk pengguna tertentu dengan kueri dari kunci utama tabel. Saat menambahkan indeks inversi, Anda akan dapat menemukan pengguna yang diikuti pengguna dengan membuat kueri indeks inversi.

Indeks inversi juga berguna untuk membuat kueri hubungan satu-ke-banyak untuk entitas yang merupakan subjek hubungan satu-ke-banyak. Anda dapat melihatnya dengan entitas Reaksi di tabel Anda. Mungkin ada beberapa reaksi pada satu foto, dan setiap reaksi akan meliputi foto dengan reaksi, nama pengguna dari pengguna yang bereaksi, dan jenis reaksi. Namun, karena pengguna bisa memiliki banyak foto, pengidentifikasi utama untuk foto ada di kunci RANGE -- PHOTO#<USERNAME>#<TIMESTAMP>. Karenanya, Anda tidak dapat menggunakan kunci utama untuk menghubungkan reaksi pada foto.

Untuk memenuhi pola akses “Lihat foto dan reaksi”, model data meletakkan pengidentifikasi foto untuk entitas Reaksi di kunci RANGE . Sekarang, ketika membuat kueri indeks inversi, Anda dapat menggunakan pengidentifikasi foto untuk memilih foto dan semua reaksinya dalam satu permintaan. Ini ditunjukkan pada Langkah 2 di bawah ini.

Waktu untuk Menyelesaikan Modul: 40 Menit


  • Langkah 1: Buat indeks sekunder

    Untuk membuat indeks sekunder, Anda menentukan kunci utama indeks, sama seperti ketika Anda membuat tabel. Perhatikan bahwa kunci utama untuk indeks sekunder global tidak harus unik. DynamoDB kemudian menyalin item ke dalam indeks berdasarkan atribut yang ditentukan, dan Anda dapat membuat kuerinya seperti pada tabel.

    Indeks inversi adalah pola umum dalam DynamoDB di mana Anda membuat indeks sekunder yang merupakan inversi kunci utama tabel Anda. Kunci HASH untuk tabel Anda ditentukan sebagai kunci RANGE di indeks sekunder, dan kunci RANGE untuk tabel Anda ditentukan sebagai kunci HASH di indeks sekunder.

    Pembuatan indeks sekunder mirip dengan pembuatan tabel. Dalam kode yang Anda unduh, terdapat file di direktori scripts/ bernama add_inverted_index.py. Konten file tersebut ditunjukkan di bawah ini.

    import boto3
    
    dynamodb = boto3.client('dynamodb')
    
    try:
        dynamodb.update_table(
            TableName='quick-photos',
            AttributeDefinitions=[
                {
                    "AttributeName": "PK",
                    "AttributeType": "S"
                },
                {
                    "AttributeName": "SK",
                    "AttributeType": "S"
                }
            ],
            GlobalSecondaryIndexUpdates=[
                {
                    "Create": {
                        "IndexName": "InvertedIndex",
                        "KeySchema": [
                            {
                                "AttributeName": "SK",
                                "KeyType": "HASH"
                            },
                            {
                                "AttributeName": "PK",
                                "KeyType": "RANGE"
                            }
                        ],
                        "Projection": {
                            "ProjectionType": "ALL"
                        },
                        "ProvisionedThroughput": {
                            "ReadCapacityUnits": 5,
                            "WriteCapacityUnits": 5
                        }
                    }
                }
            ],
        )
        print("Table updated successfully.")
    except Exception as e:
        print("Could not update table. Error:")
        print(e)
    

    Setiap kali atribut digunakan dalam kunci utama untuk tabel atau indeks sekunder, atribut harus didefinisikan di AttributeDefinitions. Kemudian, kita Membuat indeks sekunder baru di properti GlobalSecondaryIndexUpdates. Untuk indeks sekunder ini, kita menentukan nama indeks, skema kunci utama, throughput yang disediakan, dan atribut yang ingin kita proyeksikan.

    Perhatikan bahwa indeks inversi adalah nama pola desain dan bukan properti resmi di DynamoDB. Membuat indeks inversi sama seperti membuat indeks sekunder lainnya.

    Buat indeks inversi dengan menjalankan perintah di bawah ini.

    python scripts/add_inverted_index.py

    Anda akan melihat pesan berikut di konsol: “Tabel berhasil diperbarui.”

    Pada langkah berikutnya, kami akan menunjukkan bagaimana indeks inversi kami dapat digunakan untuk menemukan foto.

  • Langkah 2: Buat kueri indeks inversi untuk menemukan reaksi foto

    Sekarang kita telah mengonfigurasi indeks sekunder, mari kita gunakan untuk memenuhi beberapa pola akses.

    Untuk menggunakan indeks sekunder, Anda memiliki dua panggilan API yang tersedia -- Kueri dan Pindai. Dengan Kueri, Anda harus menentukan kunci HASH, dan hasil yang ditargetkan akan muncul. Dengan Pindai, Anda tidak menentukan kunci HASH, dan operasi berjalan di seluruh tabel Anda. Pemindaian tidak disarankan dalam DynamoDB kecuali dalam keadaan tertentu karena pemindaian mengakses setiap item di database Anda. Jika Anda memiliki banyak data dalam tabel, pemindaian dapat memakan waktu yang sangat lama

    Kita dapat menggunakan API Kueri terhadap indeks sekunder untuk menemukan semua reaksi pada foto tertentu. Seperti yang Anda lihat di modul sebelumnya, Anda dapat menggunakan kueri ini untuk mengambil dua jenis entitas dalam satu perintah. Dalam kueri ini, Anda dapat mengambil foto dan reaksinya.

    Di kode yang Anda unduh, terdapat file di direktori application/ bernama fetch_photo_and_reactions.py. Konten skrip ini ditunjukkan di bawah ini.

    import boto3
    
    from entities import Photo, Reaction
    
    dynamodb = boto3.client('dynamodb')
    
    USER = "david25"
    TIMESTAMP = '2019-03-02T09:11:30'
    
    
    def fetch_photo_and_reactions(username, timestamp):
        try:
            resp = dynamodb.query(
                TableName='quick-photos',
                IndexName='InvertedIndex',
                KeyConditionExpression="SK = :sk AND PK BETWEEN :reactions AND :user",
                ExpressionAttributeValues={
                    ":sk": { "S": "PHOTO#{}#{}".format(username, timestamp) },
                    ":user": { "S": "USER$" },
                    ":reactions": { "S": "REACTION#" },
                },
                ScanIndexForward=True
            )
        except Exception as e:
            print("Index is still backfilling. Please try again in a moment.")
            return False
    
        items = resp['Items']
        items.reverse()
    
        photo = Photo(items[0])
        photo.reactions = [Reaction(item) for item in items[1:]]
    
        return photo
    
    
    photo = fetch_photo_and_reactions(USER, TIMESTAMP)
    
    if photo:
        print(photo)
        for reaction in photo.reactions:
            print(reaction)
    

    Fungsi fetch_photo_and_reactions serupa dengan fungsi yang Anda miliki di aplikasi Anda. Fungsi menerima nama pengguna dan tanda waktu serta membuat kueri terhadap InvertedIndex guna menemukan foto dan reaksi untuk foto. Kemudian fungsi merakit item yang dihasilkan menjadi entitas Foto dan beberapa entitas Reaksi yang dapat digunakan dalam aplikasi Anda.

    python application/fetch_photo_and_reactions.py

    Anda akan melihat output foto dan lima reaksinya.

    Photo<david25 -- 2019-03-02T09:11:30>
    Reaction<ylee -- PHOTO#david25#2019-03-02T09:11:30 -- smiley>
    Reaction<kennedyheather -- PHOTO#david25#2019-03-02T09:11:30 -- smiley>
    Reaction<jenniferharris -- PHOTO#david25#2019-03-02T09:11:30 -- +1>
    Reaction<geoffrey32 -- PHOTO#david25#2019-03-02T09:11:30 -- +1>
    Reaction<chasevang -- PHOTO#david25#2019-03-02T09:11:30 -- +1>

    Perhatikan bahwa indeks sekunder memerlukan waktu untuk diisi kembali. Anda mungkin mendapatkan pesan kesalahan yang menunjukkan bahwa pengisian kembali sedang berlangsung. Jika demikian, coba lagi dalam beberapa menit.

    Pada langkah berikutnya, kita akan melihat cara menggunakan indeks inversi untuk mengambil semua pengguna yang diikuti oleh pengguna tertentu.

  • Langkah 3: Temukan pengguna yang diikuti

    Pada langkah sebelumnya, Anda melihat cara menggunakan indeks inversi untuk mengambil hubungan satu-ke-banyak untuk entitas yang merupakan subjek hubungan satu-ke-banyak. Pada langkah ini, Anda akan menggunakan indeks inversi untuk mengambil sisi “lain” hubungan banyak-ke-banyak.

    Kunci utama dalam tabel memungkinkan Anda menemukan semua pengikut pengguna tertentu, tetapi tidak akan memungkinkan Anda menemukan semua pengguna yang diikuti seseorang. Dengan indeks inversi, kunci akan terbalik -- Anda dapat menemukan semua pengguna diikuti oleh pengguna tertentu.

    Di kode yang Anda unduh, terdapat file di direktori application/ bernama find_following_for_user.py. Konten skrip ini antara lain.

    import boto3
    
    from entities import Friendship
    
    dynamodb = boto3.client('dynamodb')
    
    USERNAME = "haroldwatkins"
    
    
    def find_following_for_user(username):
        resp = dynamodb.query(
            TableName='quick-photos',
            IndexName='InvertedIndex',
            KeyConditionExpression="SK = :sk",
            ExpressionAttributeValues={
                ":sk": { "S": "#FRIEND#{}".format(username) }
            },
            ScanIndexForward=True
        )
    
        return [Friendship(item) for item in resp['Items']]
    
    
    
    follows = find_following_for_user(USERNAME)
    
    print("Users followed by {}:".format(USERNAME))
    for follow in follows:
        print(follow)
    

    Fungsi find_following_for_user serupa dengan fungsi yang Anda miliki di aplikasi Anda. Fungsi menerima nama pengguna untuk siapa Anda ingin menemukan pengguna yang diikuti. Fungsi tersebut kemudian membuat kueri indeks inversi untuk menemukan semua entitas Pertemanan di mana pengguna yang mengikuti merupakan nama pengguna yang diberikan.

    Jalankan skrip dengan menjalankan perintah berikut di terminal Anda.

    python application/find_following_for_user.py

    Konsol Anda harus menampilkan daftar pengguna yang diikuti menurut nama pengguna yang diberikan:

    Users followed by haroldwatkins:
    Friendship<chasevang -- haroldwatkins>
    Friendship<david25 -- haroldwatkins>
    Friendship<frankhall -- haroldwatkins>
    Friendship<geoffrey32 -- haroldwatkins>
    Friendship<jacksonjason -- haroldwatkins>
    Friendship<natasha87 -- haroldwatkins>
    Friendship<nmitchell -- haroldwatkins>
    Friendship<ppierce -- haroldwatkins>
    Friendship<tmartinez -- haroldwatkins>
    Friendship<vpadilla -- haroldwatkins>

    Perhatikan bahwa meskipun ini menghasilkan semua entitas Pertemanan untuk pengguna, informasi dalam entitas Pertemanan cukup jarang. Ini hanya mencakup nama pengguna dari pengguna yang diikuti tetapi bukan profil pengguna lengkap. Dalam modul berikutnya, kita akan membahas cara menggunakan normalisasi parsial untuk menangani situasi seperti ini secara efisien.

  • Penutup

    Dalam modul ini, kami menambahkan indeks sekunder ke tabel menggunakan pola indeks inversi. Penambahan ini memenuhi dua pola akses tambahan:

    • Melihat foto dan reaksi (Baca)
    • Melihat yang diikuti untuk pengguna (Baca)

    Saat mengambil semua pengguna yang diikuti untuk pengguna, kami melihat masalah bahwa setiap entitas Pertemanan kehilangan informasi tentang pengguna yang diikuti. Dalam modul berikutnya, kita akan melihat cara menggunakan normalisasi parsial untuk membantu dengan pola akses ini.