En este módulo, aprenderá mediante ejemplos sencillos a recuperar múltiples elementos en una llamada a la API con DynamoDB. También aprenderá a utilizar los índices secundarios para permitir patrones de consulta adicionales en las tablas de DynamoDB.

Tiempo para completar el módulo: 15 minutos


En el Módulo 2, se demostró cómo recuperar un único libro de una tabla de DynamoDB mediante el uso de la llamada a la API GetItem. Se trata de un patrón de acceso útil, pero la aplicación también debe tener la capacidad de recuperar varios elementos en una llamada. Por ejemplo, quizá quiera recuperar todos los libros escritos por John Grisham a fin de mostrarlos a los usuarios. En el paso 1 de este módulo, se utiliza la API Query para recuperar todos los libros escritos por un autor específico.

Tanto la llamada a la API GetItem para obtener un único libro como la llamada a la API Query para recuperar todos los libros escritos por un autor utilizan la clave primaria especificada en la tabla de Libros . Sin embargo, es posible que desee habilitar patrones de acceso adicionales, como recuperar todos los libros de una categoría, como historia o biografías. La Categoría no hace parte de la clave primaria de la tabla, pero se puede crear un índice secundario a fin de permitir patrones de acceso adicionales. En los pasos 2 y 3 de este módulo, se creará y consultará un índice secundario.


  • Paso 1. Recupere varios elementos mediante una consulta

    Si la tabla utiliza una clave primaria compuesta, se pueden recuperar todos los elementos mediante la misma clave hash a través de la llamada a la API Query . Para la aplicación, esto significa que se pueden recuperar todos los libros con el mismo atributo de Autor .

    Ejecute el siguiente comando en la terminal de AWS Cloud9.

    $ python query_items.py

    Este comando ejecuta el siguiente script que recupera todos los libros escritos por 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)

    Tras la ejecución del script, deben aparecer dos libros de John Grisham, The Firm y 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'}

    La recuperación de varios elementos mediante una sola llamada en DynamoDB es un patrón común fácil de usar con la llamada a la API Query .

  • Paso 2. Crear un índice secundario

    DynamoDB permite la creación de índices secundarios para obtener más patrones de acceso a los datos en la tabla. Los índices secundarios son un medio eficaz para agregar flexibilidad de consulta a la tabla de DynamoDB.

    DynamoDB tiene dos tipos de índices secundarios: los índices secundarios globales y los índices secundarios locales. En esta sección, se agrega un índice secundario global al atributo de categoría. Este permitirá recuperar todos los libros de una categoría específica.

    El siguiente ejemplo de script agrega un índice secundario global a una tabla existente.

    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)

    Crear un índice secundario global es muy parecido a crear una tabla. Se especifican el nombre del índice, los atributos que estarán dentro del índice, el esquema de la clave del índice y el rendimiento aprovisionado (la capacidad máxima que una aplicación puede consumir de una tabla o de un índice). El rendimiento aprovisionado en cada índice es independiente del rendimiento aprovisionado en una tabla. Esto permite definir el rendimiento con detalle a fin de satisfacer las necesidades de la aplicación.

    Ejecute el siguiente comando en la terminal para agregar el índice secundario global.

    $ python add_secondary_index.py

    El script agrega un índice secundario global llamado CategoryIndex a la tabla de Libros.

  • Paso 3. Consultar un índice secundario

    Ahora que tiene CategoryIndex, podrá utilizarlo para recuperar todos los libros de una categoría específica. Utilizar un índice secundario para consultar una tabla es parecido a utilizar la llamada a la API Query . Ahora se agrega el nombre del índice a la llamada a la API.

    Al agregar un índice secundario global a una tabla existente, DynamoDB rellena de manera asíncrona el índice con los elementos existentes en la tabla. Tras la replicación de todos los elementos, el índice queda disponible para las consultas. La duración de la replicación varía en función del tamaño de la tabla.

    Puede utilizar el script query_with_index.py para consultar el nuevo índice. Ejecute el script en su terminal con el siguiente comando.

    $ python query_with_index.py

    El comando ejecuta el siguiente script para recuperar todos los libros en la tienda que pertenecen a la Categoría de Suspenso.

    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)

    Observe que una parte del script espera hasta que el índice esté disponible para las consultas.

    Debe ver los siguientes resultados en la terminal.

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

    La consulta arroja tres libros escritos por dos autores diferentes. Este es un patrón de consulta que habría sido difícil de obtener con el esquema de la clave principal de la tabla, pero es fácil de implementar gracias a las capacidades de los índices secundarios.


    En el siguiente módulo, aprenderá a actualizar los atributos de un elemento existente en una tabla mediante la API UpdateItem