Bu modülde, DynamoDB ile tek API çağrısıyla birden fazla öğe almaya ilişkin bazı basit örneklerin üzerinden geçeceksiniz. Ayrıca, ikincil dizinleri kullanarak DynamoDB tablolarınızda ek sorgulama modellerini nasıl etkinleştirebileceğinizi de öğreneceksiniz.

Modülü Tamamlama Süresi: 15 Dakika


2. Modül’de, GetItem API çağrısını kullanarak DynamoDB veritabanından tek bir kitabı nasıl alabileceğinizi görmüştünüz. Bu erişim modeli kullanışlı olmakla birlikte, uygulamanızın tek çağrıda birden fazla öğeyi alabilmesi de gereklidir. Örneğin, kullanıcılara sergileyebilmek için John Grisham tarafından yazılan tüm kitapları almak isteyebilirsiniz. Bu modülün 1. Adımında, belirli bir yazara ait tüm kitapları almak için Query API’sini kullanırsınız.

Hem tek bir kitabı almaya yarayan GetItem API çağrısı hem de bir yazara ait tüm kitapları almaya yarayan Query API çağrısı Books tablonuzda belirtilen birincil anahtarı kullanır. Bununla birlikte, tarih veya biyografi gibi belirli bir kategoride yer alan tüm kitapları almak gibi ek erişim modellerini de etkinleştirmek isteyebilirsiniz. Category, tablonuzun birincil anahtarının bir parçası değildir ancak ek erişim modellerini mümkün kılmak için bir ikincil dizin oluşturabilirsiniz. Bu modülün 2. ve 3. Adımlarında bir ikincil dizin oluşturacak ve bu ikincil dizini sorgulayacaksınız.


  • 1. Adım. Bir sorguyla birden fazla öğe alma

    Tablonuz birleşik birincil anahtar kullanıyorsa, Query API çağrısını kullanarak aynı karma anahtara sahip tüm öğeleri alabilirsiniz. Uygulamanız için bunun anlamı, aynı Author özniteliğine sahip tüm kitapları alabileceğinizdir.

    AWS Cloud9 terminalinde aşağıdaki komutu çalıştırın.

    $ python query_items.py

    Bu komut, John Grisham tarafından yazılan tüm kitapları alan aşağıdaki betiği çalıştırır.

    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)

    Betiği çalıştırdıktan sonra The Firm ve The Rainmaker olmak üzere John Grisham’a ait iki kitabı görmeniz gerekir.

    $ 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'}

    DynamoDB’de tek bir çağrıyla birden fazla öğeyi almak yaygın bir modeldir ve bunun Query API çağrısıyla yapılması kolaydır.

  • 2. Adım. İkincil dizin oluşturma

    DynamoDB, tablonuzda ek veri erişimi modellerine karşılık gelen ikincil dizinler oluşturmanıza olanak tanır. İkincil dizinler, DynamoDB tablosuna sorgu esnekliği katmanın güçlü bir yoludur.

    DynamoDB’de küresel ikincil dizinler ve yerel ikincil dizinler olmak üzere iki tür ikincil dizin bulunur. Bu bölümde, Kategori özniteliğinize belirli bir kategorideki tüm kitapları almanıza olanak tanıyacak bir küresel ikincil dizin eklersiniz.

    Aşağıdaki betik örneği mevcut bir tabloya bir küresel ikincil dizin ekler.

    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)

    Küresel ikincil dizin oluşturma ile tablo oluşturmanın çok sayıda ortak yönü vardır. Dizin için bir ad, dizinde yer alacak öznitelikler, dizinin anahtar şeması ve tedarik edilen aktarım hızı (bir uygulamanın bir tablo veya dizinden kullanabileceği maksimum kapasite) belirtirsiniz. Her dizinin tedarik edilen aktarım hızı, bir tablonun tedarik edilen aktarım hızından ayrıdır. Bu, aktarım hızını uygulamanızın ihtiyaçlarını karşılayacak şekilde ayrıntılı olarak tanımlamanıza olanak tanır.

    Küresel ikincil dizininizi eklemek için terminalinizde aşağıdaki komutu çalıştırın.

    $ python add_secondary_index.py

    Bu betik, Books tablonuza CategoryIndex adı verilen bir küresel ikincil dizin ekler.

  • 3. Adım. İkincil dizini sorgulama

    Artık CategoryIndex’e sahip olduğunuza göre, bunu kullanarak belirli bir kategorideki tüm kitapları alabilirsiniz. Bir tabloyu sorgulamak için ikincil dizin kullanmak, Query API çağrısını kullanmaya benzerdir. Şimdi dizin adını API çağrısına ekliyorsunuz.

    Mevcut tabloya bir küresel ikincil dizin eklediğinizde DynamoDB, dizini tablodaki mevcut öğelerle zaman uyumsuz olarak geri doldurur. Tüm öğeler geri doldurulduktan sonra dizin sorgulamaya hazır hale gelir. Geri doldurma zamanı, tablonun boyutuna göre değişiklik gösterir.

    Yeni dizine göre sorgulama yapmak için query_with_index.py betiğini kullanabilirsiniz. Betiği aşağıdaki komutla terminalinizde çalıştırın:

    $ python query_with_index.py

    Bu komut, aşağıdaki betiği çalıştırarak mağazadaki Suspense Category içinde yer alan tüm kitapları alır.

    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)

    Betiğin, dizin sorgulamaya hazır hale gelene kadar bekleyen bir kısmı olduğunu unutmayın.

    Terminalinizde aşağıdaki çıktıları görmeniz gerekir.

    $ 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'}

    Sorgulama sonucunda iki farklı yazara ait üç kitap bulunmuştur. Bu, tablonuzun ana anahtar şeması ile zor ancak ikincil dizinlerin sağladığı güç ile kolay uygulanacak bir sorgulama modelidir.


    Bir sonraki modülde, bir tabloda yer alan mevcut bir öğenin özniteliklerini UpdateItem API’sini kullanarak nasıl güncelleyebileceğinizi öğreneceksiniz.