

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Creación de una aplicación de publicación sencilla con los solucionadores de DynamoDB
<a name="tutorial-dynamodb-resolvers"></a>

**nota**  
Ahora admitimos de forma básica el tiempo de ejecución APPSYNC\$1JS y su documentación. Considere la opción de utilizar el tiempo de ejecución APPSYNC\$1JS y sus guías [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html).

En este tutorial, se muestra cómo puede incorporar sus propias tablas de Amazon DynamoDB y conectarlas AWS AppSync a una API de GraphQL.

Puede permitir el AWS AppSync aprovisionamiento de recursos de DynamoDB en su nombre. O bien, si lo prefiere, puede conectar las tablas existentes a un esquema de GraphQL creando un origen de datos y un solucionador. En cualquier caso, podrá leer y escribir en la base de datos de DynamoDB a través de instrucciones de GraphQL y suscribirse a datos en tiempo real.

Hay que realizar una serie de pasos de configuración específicos para que las instrucciones de GraphQL se traduzcan a operaciones de DynamoDB y que, a su vez, las respuestas se traduzcan de nuevo a GraphQL. En este tutorial se describe el proceso de configuración a través de varios escenarios y patrones de acceso a datos del mundo real.

## Configuración de las tablas de DynamoDB
<a name="setting-up-your-ddb-tables"></a>

Para comenzar este tutorial, primero debe seguir los pasos que se indican a continuación para AWS aprovisionar los recursos.

1.  AWS Aprovisione recursos mediante la siguiente AWS CloudFormation plantilla de la CLI:

   ```
   aws cloudformation create-stack \
       --stack-name AWSAppSyncTutorialForAmazonDynamoDB \
       --template-url https://s3.us-west-2.amazonaws.com/awsappsync/resources/dynamodb/AmazonDynamoDBCFTemplate.yaml \
       --capabilities CAPABILITY_NAMED_IAM
   ```

   Como alternativa, puedes lanzar la siguiente CloudFormation pila en la región US-West 2 (Oregón) de tu AWS cuenta.

   [https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/dynamodb/AmazonDynamoDBCFTemplate.yaml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/dynamodb/AmazonDynamoDBCFTemplate.yaml)

   Así se crea lo siguiente:
   + Una tabla de DynamoDB llamada `AppSyncTutorial-Post` que contendrá datos de `Post`.
   + Un rol de IAM y una política gestionada de IAM asociada para poder interactuar con AWS AppSync la tabla. `Post`

1. Para ver más información acerca de la pila y de los recursos creados, ejecute el siguiente comando de la CLI:

   ```
   aws cloudformation describe-stacks --stack-name AWSAppSyncTutorialForAmazonDynamoDB
   ```

1. Para eliminar los recursos más adelante, puede ejecutar lo siguiente:

   ```
   aws cloudformation delete-stack --stack-name AWSAppSyncTutorialForAmazonDynamoDB
   ```

## Creación de la API de GraphQL
<a name="creating-your-graphql-api"></a>

Para crear la API GraphQL en: AWS AppSync

1. Inicia sesión en la [AppSync consola Consola de administración de AWS](https://console.aws.amazon.com/appsync/) y ábrela.

   1. En el **APIs panel**, selecciona **Crear API**.

1. En la ventana **Personalice su API o impórtela desde Amazon DynamoDB**, seleccione **Crear desde cero**.

   1. Seleccione **Comenzar** a la derecha de la misma ventana.

1. En el campo **Nombre de la API**, establezca el nombre de la API en `AWSAppSyncTutorial`.

1. Seleccione **Crear**.

La AWS AppSync consola crea una nueva API de GraphQL para usted mediante el modo de autenticación con clave de API. Puede utilizar la consola para configurar el resto de la API de GraphQL y ejecutar consultas en ella durante el resto de este tutorial.

## Definición de una API de publicación básica
<a name="defining-a-basic-post-api"></a>

Ahora que ha creado una API de AWS AppSync GraphQL, puede configurar un esquema básico que permita la creación, recuperación y eliminación básicas de los datos posteriores.

1. [Inicia sesión en la consola Consola de administración de AWS y ábrelaAppSync .](https://console.aws.amazon.com/appsync/)

   1. En el **APIs panel de control**, elige la API que acabas de crear.

1. En la **barra lateral**, seleccione **Esquema**.

   1. En la página **Esquema**, sustituya el contenido por el código siguiente:

     ```
     schema {
         query: Query
         mutation: Mutation
     }
     
     type Query {
         getPost(id: ID): Post
     }
     
     type Mutation {
         addPost(
             id: ID!
             author: String!
             title: String!
             content: String!
             url: String!
         ): Post!
     }
     
     type Post {
         id: ID!
         author: String
         title: String
         content: String
         url: String
         ups: Int!
         downs: Int!
         version: Int!
     }
     ```

1. Seleccione **Save**.

Este esquema define un tipo `Post` y las operaciones para agregar y obtener objetos `Post`.

## Configuración del origen de datos para las tablas de DynamoDB
<a name="configuring-the-data-source-for-the-ddb-tables"></a>

A continuación, vincule las consultas y las mutaciones definidas en el esquema a la tabla `AppSyncTutorial-Post` de DynamoDB.

En primer lugar, AWS AppSync debe conocer sus tablas. Para ello, configure un origen de datos en AWS AppSync:

1. Inicie sesión en la [AppSync consola Consola de administración de AWS y ábrala](https://console.aws.amazon.com/appsync/).

   1. En el **APIs panel**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Origen de datos**.

1. Elija **Crear origen de datos**.

   1. En **Nombre de origen de datos**, escriba `PostDynamoDBTable`. 

   1. En **Tipo de origen de datos**, elija **Tabla de Amazon DynamoDB**.

   1. En **Región**, elija **US-WEST-2**.

   1. **En Nombre de tabla**, elija la tabla **AppSyncTutorial-Post DynamoDB**.

   1. Cree un nuevo rol de IAM (recomendado) o elija un rol existente que tenga el permiso de IAM `lambda:invokeFunction`. Los roles existentes necesitan una política de confianza, tal y como se explica en la sección [Asociar un origen de datos](attaching-a-data-source.md). 

      El siguiente es un ejemplo de política de IAM que tiene los permisos necesarios para llevar a cabo operaciones en el recurso:

------
#### [ JSON ]

****  

      ```
      { 
           "Version":"2012-10-17",		 	 	  
           "Statement": [ 
               { 
                   "Effect": "Allow", 
                   "Action": [ "lambda:invokeFunction" ], 
                   "Resource": [ 
                       "arn:aws:lambda:us-east-1:111122223333:function:myFunction", 
                       "arn:aws:lambda:us-east-1:111122223333:function:myFunction:*" 
                   ] 
               } 
           ] 
       }
      ```

------

1. Seleccione **Crear**.

## Configuración del solucionador AddPost (DynamoDB) PutItem
<a name="setting-up-the-addpost-resolver-dynamodb-putitem"></a>

**Una vez AWS AppSync que conozca la tabla de DynamoDB, podrá vincularla a consultas y mutaciones individuales definiendo Resolvers.** El primer solucionador que va a crear es `addPost`, que le permite crear una publicación en la tabla `AppSyncTutorial-Post` de DynamoDB.

Un solucionador tiene los siguientes componentes:
+ La ubicación en el esquema de GraphQL donde se asocia el solucionador. En este caso configuramos en el campo `addPost` un solucionador de tipo `Mutation`. El solucionador se invocará cuando el intermediario llame a `mutation { addPost(...){...} }`.
+ El origen de datos que se va a utilizar para el solucionador. En este caso, queremos utilizar el origen de datos `PostDynamoDBTable` definido anteriormente para poder agregar entradas en la tabla `AppSyncTutorial-Post` de DynamoDB.
+ La plantilla de mapeo de solicitudes. El propósito de la plantilla de mapeo de solicitudes es tomar la solicitud entrante de la persona que llama y traducirla en instrucciones AWS AppSync para su ejecución en DynamoDB.
+ La plantilla de mapeo de respuestas. El cometido de la plantilla de mapeo de respuesta es tomar la respuesta de DynamoDB y traducirla de nuevo a algo que GraphQL espera. Esto resulta útil si la forma de los datos en DynamoDB es diferente del tipo `Post` en GraphQL. Como este caso sí tienen la misma forma, solo hay que transmitir los datos.

Para configurar el solucionador de :

1. [Inicie sesión en la consola Consola de administración de AWS y ábrala. AppSync ](https://console.aws.amazon.com/appsync/)

   1. En el **APIs panel**, elige tu API de GraphQL.

   1. En la **barra lateral**, seleccione **Origen de datos**.

1. Elija **Crear origen de datos**.

   1. En **Nombre de origen de datos**, escriba `PostDynamoDBTable`. 

   1. En **Tipo de origen de datos**, elija **Tabla de Amazon DynamoDB**.

   1. En **Región**, elija **US-WEST-2**.

   1. **En Nombre de tabla**, elija la tabla **AppSyncTutorial-Post DynamoDB**.

   1. Cree un nuevo rol de IAM (recomendado) o elija un rol existente que tenga el permiso de IAM `lambda:invokeFunction`. Los roles existentes necesitan una política de confianza, tal y como se explica en la sección [Asociar un origen de datos](attaching-a-data-source.md). 

      El siguiente es un ejemplo de política de IAM que tiene los permisos necesarios para llevar a cabo operaciones en el recurso:

------
#### [ JSON ]

****  

      ```
      { 
           "Version":"2012-10-17",		 	 	  
           "Statement": [ 
               { 
                   "Effect": "Allow", 
                   "Action": [ "lambda:invokeFunction" ], 
                   "Resource": [ 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction", 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction:*" 
                   ] 
               } 
           ] 
       }
      ```

------

1. Seleccione **Crear**.

1. Elija la pestaña **Schema (Esquema)**.

1. En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **addPost** en el tipo **Mutation** y, a continuación, seleccione **Attach (Asociar)**.

1. En el **menú Acción**, seleccione **Actualizar tiempo de ejecución** y, a continuación, elija **Solucionador de unidades (solo VTL)**.

1. En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.

1. En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

   ```
   {
       "version" : "2017-02-28",
       "operation" : "PutItem",
       "key" : {
           "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
       },
       "attributeValues" : {
           "author" : $util.dynamodb.toDynamoDBJson($context.arguments.author),
           "title" : $util.dynamodb.toDynamoDBJson($context.arguments.title),
           "content" : $util.dynamodb.toDynamoDBJson($context.arguments.content),
           "url" : $util.dynamodb.toDynamoDBJson($context.arguments.url),
           "ups" : { "N" : 1 },
           "downs" : { "N" : 0 },
           "version" : { "N" : 1 }
       }
   }
   ```

   **Nota**: se especifica un *tipo* para todas las claves y valores de atributos. Por ejemplo, puede establecer el campo `author` como `{ "S" : "${context.arguments.author}" }`. La `S` parte indica a DynamoDB AWS AppSync y a DynamoDB que el valor será un valor de cadena. El valor real se rellena con el argumento `author`. Del mismo modo, el campo `version` es numérico, ya que utiliza `N` para el tipo. Por último, también inicializamos los campos `ups`, `downs` y `version`.

   En este tutorial, especificó que el `ID!` tipo GraphQL, que indexa el nuevo elemento que se inserta en DynamoDB, forma parte de los argumentos del cliente. AWS AppSync viene con una utilidad para la generación automática de identificadores llamada `$utils.autoId()` que también podrías haber utilizado en forma de. `"id" : { "S" : "${$utils.autoId()}" }` Así bastaría con excluir `id: ID!` de la definición del esquema de `addPost()` y se insertaría de forma automática. No utilizará esta técnica en este tutorial, pero debe considerarla, ya que se trata de una práctica recomendada a la hora de escribir en tablas de DynamoDB.

   Para obtener más información acerca de las plantillas de mapeo, consulte la sección [Información general de plantillas de mapeo de solucionador](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview). Para obtener más información sobre el mapeo de GetItem solicitudes, consulte la documentación de [GetItem](aws-appsync-resolver-mapping-template-reference-dynamodb-getitem.md)referencia. Para obtener más información sobre los tipos, consulte la documentación de referencia del [Sistema de tipos (mapeos de solicitud)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md).

1. En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

   ```
   $utils.toJson($context.result)
   ```

    **Nota**: Debido a que la forma de los datos de la tabla `AppSyncTutorial-Post` coincide exactamente con la forma del tipo `Post` de GraphQL, la plantilla de mapeo de respuesta se limita a pasar directamente los resultados. Observe que todos los ejemplos de este tutorial utilizan la misma plantilla de mapeo de respuesta, de manera que solo tiene que crear un archivo.

1. Seleccione **Save**.

### Llame a la API para añadir una publicación
<a name="call-the-api-to-add-a-post"></a>

Ahora que el solucionador está configurado, AWS AppSync puede convertir una `addPost` mutación entrante en una operación de PutItem DynamoDB. Ahora puede ejecutar una mutación para incluir datos en la tabla.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente:

  ```
  mutation addPost {
    addPost(
      id: 123
      author: "AUTHORNAME"
      title: "Our first post!"
      content: "This is our first post."
      url: "https://aws.amazon.com/appsync/"
    ) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Los resultados de la publicación que acaba de crear deben aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "addPost": {
        "id": "123",
        "author": "AUTHORNAME",
        "title": "Our first post!",
        "content": "This is our first post.",
        "url": "https://aws.amazon.com/appsync/",
        "ups": 1,
        "downs": 0,
        "version": 1
      }
    }
  }
  ```

Esto es lo que ha ocurrido:
+ AWS AppSync recibió una solicitud de `addPost` mutación.
+ AWS AppSync tomó la solicitud y la plantilla de mapeo de la solicitud y generó un documento de mapeo de la solicitud. Esto habrá tenido el siguiente aspecto:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "PutItem",
      "key" : {
          "id" : { "S" : "123" }
      },
      "attributeValues" : {
          "author": { "S" : "AUTHORNAME" },
          "title": { "S" : "Our first post!" },
          "content": { "S" : "This is our first post." },
          "url": { "S" : "https://aws.amazon.com/appsync/" },
          "ups" : { "N" : 1 },
          "downs" : { "N" : 0 },
          "version" : { "N" : 1 }
      }
  }
  ```
+ AWS AppSync utilizó el documento de mapeo de solicitudes para generar y ejecutar una solicitud de `PutItem` DynamoDB.
+ AWS AppSync tomó los resultados de la `PutItem` solicitud y los volvió a convertir a tipos GraphQL.

  ```
  {
      "id" : "123",
      "author": "AUTHORNAME",
      "title": "Our first post!",
      "content": "This is our first post.",
      "url": "https://aws.amazon.com/appsync/",
      "ups" : 1,
      "downs" : 0,
      "version" : 1
  }
  ```
+ Después los ha pasado a través del documento de mapeo de respuesta, que se ha limitado a transferirlos sin cambios.
+ Por fin ha devuelto el objeto recién creado en la respuesta de GraphQL.

## Configuración del GetPost Resolver (DynamoDB) GetItem
<a name="setting-up-the-getpost-resolver-ddb-getitem"></a>

Ahora que puede añadir datos a la tabla de DynamoDB `AppSyncTutorial-Post`, tiene que configurar la consulta `getPost` para poder recuperar los datos de la tabla `AppSyncTutorial-Post`. Para ello, tiene que configurar otro solucionador.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **getPost** en el tipo **Query** y, a continuación, seleccione **Attach (Asociar)**.
+ En el **menú Acción**, seleccione **Actualizar tiempo de ejecución** y, a continuación, elija **Solucionador de unidades (solo VTL)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "GetItem",
      "key" : {
          "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
      }
  }
  ```
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```
+ Seleccione **Save**.

### Llame a la API para obtener una publicación
<a name="call-the-api-to-get-a-post"></a>

Ahora que el solucionador está configurado, AWS AppSync sabe cómo convertir una `getPost` consulta entrante en una operación de `GetItem` DynamoDB. Ahora puede ejecutar una consulta para recuperar la publicación que ha creado anteriormente.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue lo siguiente:

  ```
  query getPost {
    getPost(id:123) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación obtenida de DynamoDB debe aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "getPost": {
        "id": "123",
        "author": "AUTHORNAME",
        "title": "Our first post!",
        "content": "This is our first post.",
        "url": "https://aws.amazon.com/appsync/",
        "ups": 1,
        "downs": 0,
        "version": 1
      }
    }
  }
  ```

Esto es lo que ha ocurrido:
+ AWS AppSync recibió una `getPost` solicitud de consulta.
+ AWS AppSync tomó la solicitud y la plantilla de mapeo de solicitudes y generó un documento de mapeo de solicitudes. Esto habrá tenido el siguiente aspecto:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "GetItem",
      "key" : {
          "id" : { "S" : "123" }
      }
  }
  ```
+ AWS AppSync utilizó el documento de mapeo de solicitudes para generar y ejecutar una solicitud de GetItem DynamoDB.
+ AWS AppSync tomó los resultados de la `GetItem` solicitud y los volvió a convertir a tipos GraphQL.

  ```
  {
      "id" : "123",
      "author": "AUTHORNAME",
      "title": "Our first post!",
      "content": "This is our first post.",
      "url": "https://aws.amazon.com/appsync/",
      "ups" : 1,
      "downs" : 0,
      "version" : 1
  }
  ```
+ Después los ha pasado a través del documento de mapeo de respuesta, que se ha limitado a transferirlos sin cambios.
+ Entonces ha devuelto el objeto recuperado en la respuesta.

Como alternativa, vamos a tomar el siguiente ejemplo:

```
query getPost {
  getPost(id:123) {
    id
    author
    title
  }
}
```

Si la consulta `getPost` solo necesita las letras `id`, `author` y `title`, puede cambiar la plantilla de mapeo de solicitudes para utilizar expresiones de proyección que especifiquen únicamente los atributos que desee de la tabla de DynamoDB y evitar la transferencia innecesaria de datos de DynamoDB a AWS AppSync. Por ejemplo, la plantilla de mapeo de solicitudes puede tener un aspecto similar al siguiente fragmento:

```
{
    "version" : "2017-02-28",
    "operation" : "GetItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "projection" : {
     "expression" : "#author, id, title",
     "expressionNames" : { "#author" : "author"}
    }
}
```

## Crear una mutación en UpdatePost (DynamoDB) UpdateItem
<a name="create-an-updatepost-mutation-ddb-updateitem"></a>

De momento ya sabe crear y recuperar objetos `Post` en DynamoDB. A continuación va a configurar una nueva mutación que permite actualizar objetos. Para ello, utilice la operación UpdateItem DynamoDB.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Schema (Esquema)** modifique el tipo `Mutation` para agregar una nueva mutación `updatePost` de este modo:

  ```
  type Mutation {
      updatePost(
          id: ID!,
          author: String!,
          title: String!,
          content: String!,
          url: String!
      ): Post
      addPost(
          author: String!
          title: String!
          content: String!
          url: String!
      ): Post!
  }
  ```
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **updatePost** recién creado en el tipo **Mutation** y, a continuación, elija **Attach (Asociar)**.
+ En el **menú Acción**, seleccione **Actualizar tiempo de ejecución** y, a continuación, elija **Solucionador de unidades (solo VTL)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "UpdateItem",
      "key" : {
          "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
      },
      "update" : {
          "expression" : "SET author = :author, title = :title, content = :content, #url = :url ADD version :one",
          "expressionNames": {
              "#url" : "url"
          },
          "expressionValues": {
              ":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author),
              ":title" : $util.dynamodb.toDynamoDBJson($context.arguments.title),
              ":content" : $util.dynamodb.toDynamoDBJson($context.arguments.content),
              ":url" : $util.dynamodb.toDynamoDBJson($context.arguments.url),
              ":one" : { "N": 1 }
          }
      }
  }
  ```

   **Nota:** Este solucionador utiliza UpdateItem DynamoDB, que es muy diferente de la operación. PutItem En lugar de escribir el elemento completo, solo pide a DynamoDB que actualice determinados atributos. Esto se consigue mediante expresiones de actualización de DynamoDB. La expresión en sí se especifica en el campo `expression` de la sección `update`. Indica que se deben establecer los atributos `author`, `title`, `content` y URL, y a continuación incrementar el campo `version`. Los valores empleados no aparecen en la expresión en sí, que contiene marcadores de posición con nombres que comienzan con dos puntos y que luego se definen en el campo `expressionValues`. Por último, DynamoDB tiene palabras reservadas que no pueden aparecer en la `expression`. Por ejemplo, `url` es una palabra reservada, por lo que para actualizar el campo `url`, puede utilizar marcadores de posición de nombre y definirlos en el campo `expressionNames`.

  Para obtener más información sobre el mapeo de `UpdateItem` solicitudes, consulte la documentación de [UpdateItem](aws-appsync-resolver-mapping-template-reference-dynamodb-updateitem.md)referencia. Para obtener más información sobre cómo escribir expresiones de actualización, consulte la documentación de [ UpdateExpressions DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html).
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```

### Llame a la API para actualizar una publicación
<a name="call-the-api-to-update-a-post"></a>

Ahora que el solucionador está configurado, AWS AppSync sabe cómo convertir una `update` mutación entrante en una operación de `Update` DynamoDB. Ahora puede ejecutar una mutación para actualizar el elemento que escribió anteriormente.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente. También tendrá que actualizar el argumento `id` con el valor que anotó anteriormente.

  ```
  mutation updatePost {
    updatePost(
      id:"123"
      author: "A new author"
      title: "An updated author!"
      content: "Now with updated content!"
      url: "https://aws.amazon.com/appsync/"
    ) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación actualizada en DynamoDB debería aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "updatePost": {
        "id": "123",
        "author": "A new author",
        "title": "An updated author!",
        "content": "Now with updated content!",
        "url": "https://aws.amazon.com/appsync/",
        "ups": 1,
        "downs": 0,
        "version": 2
      }
    }
  }
  ```

En este ejemplo, los `downs` campos `ups` y no se modificaron porque la plantilla de mapeo de solicitudes no pedía AWS AppSync a DynamoDB que hiciera nada con esos campos. Además, el `version` campo se incrementó en 1 porque pidió AWS AppSync a DynamoDB que añadiera 1 al campo. `version`

## Modificación del UpdatePost Resolver (DynamoDB) UpdateItem
<a name="modifying-the-updatepost-resolver-dynamodb-updateitem"></a>

Se trata de un buen comienzo para la mutación `updatePost`, pero tiene dos inconvenientes:
+ Aunque solo desee actualizar un campo, tiene que actualizar todos.
+ Si dos personas modifican el objeto a la vez información podría perderse información.

Para solucionar estos problemas, va a modificar la mutación `updatePost` de manera que únicamente modifique los argumentos que se han especificado en la solicitud, y también va a agregar una condición a la operación `UpdateItem`.

1. Elija la pestaña **Schema (Esquema)**.

1. En el panel **Esquema**, modifique el campo `updatePost` del tipo `Mutation` para eliminar los signos de admiración de los argumentos `author`, `title`, `content` y `url` asegurándose de dejar sin cambios el campo `id`. Esto los convertirá en argumentos opcionales. Además, añada un nuevo argumento `expectedVersion` obligatorio.

   ```
   type Mutation {
       updatePost(
           id: ID!,
           author: String,
           title: String,
           content: String,
           url: String,
           expectedVersion: Int!
       ): Post
       addPost(
           author: String!
           title: String!
           content: String!
           url: String!
       ): Post!
   }
   ```

1. Seleccione **Save**.

1. En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **updatePost** en el tipo **Mutation**.

1. Elija abrir el **PostDynamoDBTable**solucionador existente.

1. En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, modifique la plantilla de mapeo de solicitud de este modo:

   ```
   {
       "version" : "2017-02-28",
       "operation" : "UpdateItem",
       "key" : {
           "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
       },
   
       ## Set up some space to keep track of things you're updating **
       #set( $expNames  = {} )
       #set( $expValues = {} )
       #set( $expSet = {} )
       #set( $expAdd = {} )
       #set( $expRemove = [] )
   
       ## Increment "version" by 1 **
       $!{expAdd.put("version", ":one")}
       $!{expValues.put(":one", { "N" : 1 })}
   
       ## Iterate through each argument, skipping "id" and "expectedVersion" **
       #foreach( $entry in $context.arguments.entrySet() )
           #if( $entry.key != "id" && $entry.key != "expectedVersion" )
               #if( (!$entry.value) && ("$!{entry.value}" == "") )
                   ## If the argument is set to "null", then remove that attribute from the item in DynamoDB **
   
                   #set( $discard = ${expRemove.add("#${entry.key}")} )
                   $!{expNames.put("#${entry.key}", "$entry.key")}
               #else
                   ## Otherwise set (or update) the attribute on the item in DynamoDB **
   
                   $!{expSet.put("#${entry.key}", ":${entry.key}")}
                   $!{expNames.put("#${entry.key}", "$entry.key")}
                   $!{expValues.put(":${entry.key}", { "S" : "${entry.value}" })}
               #end
           #end
       #end
   
       ## Start building the update expression, starting with attributes you're going to SET **
       #set( $expression = "" )
       #if( !${expSet.isEmpty()} )
           #set( $expression = "SET" )
           #foreach( $entry in $expSet.entrySet() )
               #set( $expression = "${expression} ${entry.key} = ${entry.value}" )
               #if ( $foreach.hasNext )
                   #set( $expression = "${expression}," )
               #end
           #end
       #end
   
       ## Continue building the update expression, adding attributes you're going to ADD **
       #if( !${expAdd.isEmpty()} )
           #set( $expression = "${expression} ADD" )
           #foreach( $entry in $expAdd.entrySet() )
               #set( $expression = "${expression} ${entry.key} ${entry.value}" )
               #if ( $foreach.hasNext )
                   #set( $expression = "${expression}," )
               #end
           #end
       #end
   
       ## Continue building the update expression, adding attributes you're going to REMOVE **
       #if( !${expRemove.isEmpty()} )
           #set( $expression = "${expression} REMOVE" )
   
           #foreach( $entry in $expRemove )
               #set( $expression = "${expression} ${entry}" )
               #if ( $foreach.hasNext )
                   #set( $expression = "${expression}," )
               #end
           #end
       #end
   
       ## Finally, write the update expression into the document, along with any expressionNames and expressionValues **
       "update" : {
           "expression" : "${expression}"
           #if( !${expNames.isEmpty()} )
               ,"expressionNames" : $utils.toJson($expNames)
           #end
           #if( !${expValues.isEmpty()} )
               ,"expressionValues" : $utils.toJson($expValues)
           #end
       },
   
       "condition" : {
           "expression"       : "version = :expectedVersion",
           "expressionValues" : {
               ":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion)
           }
       }
   }
   ```

1. Seleccione **Save**.

Esta plantilla es uno de los ejemplos más complejos. Demuestra la eficacia y flexibilidad de las plantillas de mapeo. Itera por todos los argumentos, saltando `id` y `expectedVersion`. Si el argumento tiene un valor determinado, pide AWS AppSync a DynamoDB que actualice ese atributo en el objeto de DynamoDB. Si el atributo se establece en null, pide AWS AppSync a DynamoDB que elimine ese atributo del objeto de publicación. Si no se ha especificado algún argumento, lo dejará como está. También incrementa el campo `version`.

También hay una nueva sección `condition`. Una expresión de condición permite indicar AWS AppSync a DynamoDB si la solicitud debe realizarse correctamente o no en función del estado del objeto que ya se encuentra en DynamoDB antes de realizar la operación. En este caso, solo quiere que la solicitud `UpdateItem` se realice si el campo `version` del elemento que hay en DynamoDB coincide exactamente con el argumento `expectedVersion`.

Si desea más información sobre las expresiones de condición, consulte la documentación de referencia [Expresiones de condición](aws-appsync-resolver-mapping-template-reference-dynamodb-condition-expressions.md).

### Llame a la API para actualizar una publicación
<a name="id1"></a>

Vamos a intentar actualizar el objeto `Post` con el nuevo solucionador:
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente. También tendrá que actualizar el argumento `id` con el valor que anotó anteriormente.

  ```
  mutation updatePost {
    updatePost(
      id:123
      title: "An empty story"
      content: null
      expectedVersion: 2
    ) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación actualizada en DynamoDB debería aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "updatePost": {
        "id": "123",
        "author": "A new author",
        "title": "An empty story",
        "content": null,
        "url": "https://aws.amazon.com/appsync/",
        "ups": 1,
        "downs": 0,
        "version": 3
      }
    }
  }
  ```

En esta solicitud, ha pedido a DynamoDB que actualice únicamente `title` el `content` campo AWS AppSync and. Los demás campos se quedan como estaban (salvo por el incremento del campo `version`). Hemos establecido un nuevo valor en el atributo `title` y hemos eliminado el atributo `content` de la publicación. Los campos `author`, `url`, `ups` y `downs` no se han modificado.

Intente ejecutar la solicitud de mutación de nuevo, dejándola exactamente como está. Verá una respuesta parecida a la siguiente:

```
{
  "data": {
    "updatePost": null
  },
  "errors": [
    {
      "path": [
        "updatePost"
      ],
      "data": {
        "id": "123",
        "author": "A new author",
        "title": "An empty story",
        "content": null,
        "url": "https://aws.amazon.com/appsync/",
        "ups": 1,
        "downs": 0,
        "version": 3
      },
      "errorType": "DynamoDB:ConditionalCheckFailedException",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)"
    }
  ]
}
```

La solicitud falla porque la expresión de condición se evalúa como false:
+ La primera vez que ejecutamos la solicitud, el valor del campo `version` de la publicación en DynamoDB era `2`, que coincidía con el argumento `expectedVersion`. La solicitud se realizó correctamente, lo que significa que el campo `version` se incrementó en DynamoDB a `3`.
+ La segunda vez que ejecutamos la solicitud, el valor del campo `version` de la publicación en DynamoDB era `3`, que no coincide con el argumento `expectedVersion`.

Este método suele denominarse *"bloqueo optimista"*.

Una característica de un solucionador de AWS AppSync DynamoDB es que devuelve el valor actual del objeto post en DynamoDB. Puede encontrarlo en el campo `data`, en la sección `errors` de la respuesta de GraphQL. La aplicación puede utilizar esta información para decidir cómo debe proceder. En este caso, podemos ver que el campo `version` del objeto en DynamoDB tiene el valor `3`, por lo que solo tendríamos que actualizar el argumento `expectedVersion` a `3` para que la solicitud se ejecutase de nuevo.

Para obtener más información sobre cómo gestionar los casos en que no se cumpla la condición, consulte [Expresiones de condición](aws-appsync-resolver-mapping-template-reference-dynamodb-condition-expressions.md) en la documentación de referencia de las plantillas de mapeo.

## Crear mutaciones en UpVotePost y DownVotePost (DynamoDB) UpdateItem
<a name="create-upvotepost-and-downvotepost-mutations-ddb-updateitem"></a>

El tipo `Post` tiene campos `ups` y `downs` para registrar los votos a favor y en contra, pero hasta el momento la API no nos deja hacer nada con ellos. Vamos a agregar algunas mutaciones para votar a favor o en contra de las publicaciones.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Schema (Schema)**, modifique el tipo `Mutation` para agregar las nuevas mutaciones `upvotePost` y `downvotePost`, de este modo:

  ```
  type Mutation {
      upvotePost(id: ID!): Post
      downvotePost(id: ID!): Post
      updatePost(
          id: ID!,
          author: String,
          title: String,
          content: String,
          url: String,
          expectedVersion: Int!
      ): Post
      addPost(
          author: String!,
          title: String!,
          content: String!,
          url: String!
      ): Post!
  }
  ```
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **upvotePost** recién creado en el tipo **Mutation** y, a continuación, elija **Attach (Asociar)**.
+ En el **menú Acción**, seleccione **Actualizar tiempo de ejecución** y, a continuación, elija **Solucionador de unidades (solo VTL)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "UpdateItem",
      "key" : {
          "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
      },
      "update" : {
          "expression" : "ADD ups :plusOne, version :plusOne",
          "expressionValues" : {
              ":plusOne" : { "N" : 1 }
          }
      }
  }
  ```
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo `downvotePost` recién creado en el tipo **Mutation** y, a continuación, elija **Attach (Asociar)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "UpdateItem",
      "key" : {
          "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
      },
      "update" : {
          "expression" : "ADD downs :plusOne, version :plusOne",
          "expressionValues" : {
              ":plusOne" : { "N" : 1 }
          }
      }
  }
  ```
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```
+ Seleccione **Save**.

### Llame a la API para votar a favor o en contra de una publicación
<a name="call-the-api-to-upvote-and-downvote-a-post"></a>

Una vez configurados los nuevos resolutores, AWS AppSync sabe cómo traducir una operación entrante `upvotePost` o de `downvote` mutación a DynamoDB UpdateItem . Ahora puede ejecutar mutaciones para votar a favor o en contra de la publicación que ha creado anteriormente.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente. También tendrá que actualizar el argumento `id` con el valor que anotó anteriormente.

  ```
  mutation votePost {
    upvotePost(id:123) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación se actualiza en DynamoDB y debe aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "upvotePost": {
        "id": "123",
        "author": "A new author",
        "title": "An empty story",
        "content": null,
        "url": "https://aws.amazon.com/appsync/",
        "ups": 6,
        "downs": 0,
        "version": 4
      }
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** algunas veces más. Debería ver cómo se incrementan en 1 los campos `ups` y `version` cada vez que ejecuta la consulta.
+ Modifique la consulta para llamar a la mutación `downvotePost` de este modo:

  ```
  mutation votePost {
    downvotePost(id:123) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja). En esta ocasión, debería ver cómo se incrementan en 1 los campos `downs` y `version` cada vez que ejecuta la consulta.

  ```
  {
    "data": {
      "downvotePost": {
        "id": "123",
        "author": "A new author",
        "title": "An empty story",
        "content": null,
        "url": "https://aws.amazon.com/appsync/",
        "ups": 6,
        "downs": 4,
        "version": 12
      }
    }
  }
  ```

## Configuración del solucionador DeletePost (DynamoDB) DeleteItem
<a name="setting-up-the-deletepost-resolver-ddb-deletepost"></a>

La próxima mutación que desea configurar es la eliminación de una publicación. Para ello, utilizará la operación `DeleteItem` de DynamoDB.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Schema (Esquema)** modifique el tipo `Mutation` para agregar una nueva mutación `deletePost` de este modo:

  ```
  type Mutation {
      deletePost(id: ID!, expectedVersion: Int): Post
      upvotePost(id: ID!): Post
      downvotePost(id: ID!): Post
      updatePost(
          id: ID!,
          author: String,
          title: String,
          content: String,
          url: String,
          expectedVersion: Int!
      ): Post
      addPost(
          author: String!,
          title: String!,
          content: String!,
          url: String!
      ): Post!
  }
  ```

  Esta vez hemos declarado el campo `expectedVersion` como opcional, lo que se explica más adelante al añadir la plantilla de mapeo de solicitud.
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **delete** recién creado en el tipo **Mutation** y, a continuación, elija **Attach (Asociar)**.
+ En el **menú Acción**, seleccione **Actualizar tiempo de ejecución** y, a continuación, elija **Solucionador de unidades (solo VTL)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "DeleteItem",
      "key": {
          "id": $util.dynamodb.toDynamoDBJson($context.arguments.id)
      }
      #if( $context.arguments.containsKey("expectedVersion") )
          ,"condition" : {
              "expression"       : "attribute_not_exists(id) OR version = :expectedVersion",
              "expressionValues" : {
                  ":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion)
              }
          }
      #end
  }
  ```

   **Nota**: el argumento `expectedVersion` es opcional. Si el intermediario ha establecido un argumento `expectedVersion` en la solicitud, entonces la plantilla añade una condición que solo permitirá que la solicitud `DeleteItem` se atienda cuando el elemento se haya eliminado o cuando el atributo `version` de la publicación en DynamoDB coincida exactamente con `expectedVersion`. Si se omite, no se especificará ninguna expresión de condición para la solicitud `DeleteItem`. Se realizará correctamente independientemente del valor de `version` o de si el elemento existe o no en DynamoDB.
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```

   **Note:** Aunque se trate de eliminar un elemento, puede devolver el elemento eliminado, siempre que no se haya eliminado previamente.
+ Seleccione **Save**.

Para obtener más información sobre el mapeo de `DeleteItem` solicitudes, consulte la documentación de referencia. [DeleteItem](aws-appsync-resolver-mapping-template-reference-dynamodb-deleteitem.md)

### Llame a la API para eliminar una publicación
<a name="call-the-api-to-delete-a-post"></a>

Ahora que el solucionador está configurado, AWS AppSync sabe cómo convertir una `delete` mutación entrante en una operación de `DeleteItem` DynamoDB. Ahora ya podemos ejecutar una mutación para eliminar datos de la tabla.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente. También tendrá que actualizar el argumento `id` con el valor que anotó anteriormente.

  ```
  mutation deletePost {
    deletePost(id:123) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación se elimina de DynamoDB. Tenga en cuenta que AWS AppSync devuelve el valor del elemento que se eliminó de DynamoDB, que debería aparecer en el panel de resultados a la derecha del panel de consulta. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "deletePost": {
        "id": "123",
        "author": "A new author",
        "title": "An empty story",
        "content": null,
        "url": "https://aws.amazon.com/appsync/",
        "ups": 6,
        "downs": 4,
        "version": 12
      }
    }
  }
  ```

El valor solo se devuelve si esta llamada a `deletePost` es realmente la que lo elimina de DynamoDB.
+ Elija **Execute query (Ejecutar consulta)** de nuevo.
+ La llamada se sigue ejecutando con éxito, pero no se devuelve ningún valor.

  ```
  {
    "data": {
      "deletePost": null
    }
  }
  ```

Ahora vamos a probar a eliminar una publicación, pero esta vez especificando `expectedValue`. Primero tiene que crear una nueva, porque acaba de eliminar la publicación con la que ha estado trabajando hasta ahora.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente:

  ```
  mutation addPost {
    addPost(
      id:123
      author: "AUTHORNAME"
      title: "Our second post!"
      content: "A new post."
      url: "https://aws.amazon.com/appsync/"
    ) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Los resultados de la publicación que acaba de crear deben aparecer en el panel de resultados a la derecha del panel de consultas. Anote el `id` del objeto recién creado, pues lo necesitaremos en breve. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "addPost": {
        "id": "123",
        "author": "AUTHORNAME",
        "title": "Our second post!",
        "content": "A new post.",
        "url": "https://aws.amazon.com/appsync/",
        "ups": 1,
        "downs": 0,
        "version": 1
      }
    }
  }
  ```

Ahora intentaremos eliminar esta publicación, pero especificaremos un valor erróneo en `expectedVersion`:
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente. También tendrá que actualizar el argumento `id` con el valor que anotó anteriormente.

  ```
  mutation deletePost {
    deletePost(
      id:123
      expectedVersion: 9999
    ) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).

  ```
  {
    "data": {
      "deletePost": null
    },
    "errors": [
      {
        "path": [
          "deletePost"
        ],
        "data": {
          "id": "123",
          "author": "AUTHORNAME",
          "title": "Our second post!",
          "content": "A new post.",
          "url": "https://aws.amazon.com/appsync/",
          "ups": 1,
          "downs": 0,
          "version": 1
        },
        "errorType": "DynamoDB:ConditionalCheckFailedException",
        "locations": [
          {
            "line": 2,
            "column": 3
          }
        ],
        "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)"
      }
    ]
  }
  ```

  La solicitud falla, porque la expresión de condición se evalúa como false: el valor de `version` de la publicación en DynamoDB no coincide con el `expectedValue` especificado en los argumentos. El valor actual del objeto se devuelve en el campo `data` de la sección `errors` de la respuesta de GraphQL.
+ Vuelva a intentar la solicitud, pero corrija `expectedVersion`:

  ```
  mutation deletePost {
    deletePost(
      id:123
      expectedVersion: 1
    ) {
      id
      author
      title
      content
      url
      ups
      downs
      version
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Esta vez la solicitud se realiza correctamente y se devuelve el valor eliminado en DynamoDB:

  ```
  {
    "data": {
      "deletePost": {
        "id": "123",
        "author": "AUTHORNAME",
        "title": "Our second post!",
        "content": "A new post.",
        "url": "https://aws.amazon.com/appsync/",
        "ups": 1,
        "downs": 0,
        "version": 1
      }
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** de nuevo.
+ La llamada sigue realizándose, pero esta vez no se devuelve ningún valor, ya que la publicación ya se había eliminado en DynamoDB.

```
{
  "data": {
    "deletePost": null
  }
}
```

## Configuración del solucionador allPost (Scan en DynamoDB)
<a name="setting-up-the-allpost-resolver-dynamodb-scan"></a>

Hasta ahora, la API solo es útil si conoce el `id` de cada publicación que desea ver. Añada un nuevo solucionador que devuelva todas las publicaciones en la tabla.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Schema (Esquema)** modifique el tipo `Query` para agregar una nueva consulta `allPost`, de este modo:

  ```
  type Query {
      allPost(count: Int, nextToken: String): PaginatedPosts!
      getPost(id: ID): Post
  }
  ```
+ Añada un nuevo tipo `PaginationPosts`:

  ```
  type PaginatedPosts {
      posts: [Post!]!
      nextToken: String
  }
  ```
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **allPost** recién creado en el tipo **Query** y, a continuación, elija **Attach (Asociar)**.
+ En el **menú Acción**, seleccione **Actualizar tiempo de ejecución** y, a continuación, elija **Solucionador de unidades (solo VTL)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "Scan"
      #if( ${context.arguments.count} )
          ,"limit": $util.toJson($context.arguments.count)
      #end
      #if( ${context.arguments.nextToken} )
          ,"nextToken": $util.toJson($context.arguments.nextToken)
      #end
  }
  ```

  Este solucionador tiene dos argumentos opcionales: `count`, que especifica el número máximo de elementos que se devolverán en una sola llamada, y `nextToken`, que se puede utilizar para recuperar el siguiente conjunto de resultados (más adelante mostrará de dónde procede el valor de `nextToken`).
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  {
      "posts": $utils.toJson($context.result.items)
      #if( ${context.result.nextToken} )
          ,"nextToken": $util.toJson($context.result.nextToken)
      #end
  }
  ```

   **Nota:** esta plantilla de mapeo de respuesta es diferente de todas las que hemos visto hasta ahora. El resultado de la consulta `allPost` es del tipo `PaginatedPosts`, que contiene una lista de publicaciones y un token de paginación. La forma de este objeto es diferente a la que devuelve el AWS AppSync DynamoDB Resolver: `items` en los resultados del DynamoDB Resolver se consulta la lista de publicaciones, AWS AppSync pero se invoca. `posts` `PaginatedPosts`
+ Seleccione **Save**.

Si desea más información sobre el mapeo de solicitud `Scan`, consulte la documentación de referencia de [Scan](aws-appsync-resolver-mapping-template-reference-dynamodb-scan.md).

### Llame a la API para escanear todas las publicaciones
<a name="call-the-api-to-scan-all-posts"></a>

Ahora que el solucionador está configurado, AWS AppSync sabe cómo convertir una `allPost` consulta entrante en una operación de `Scan` DynamoDB. Ahora puede recorrer la tabla para obtener todas las publicaciones.

Sin embargo, antes de probarlo, debe rellenar la tabla datos, ya que hemos eliminado las publicaciones con las que hemos estado trabajado hasta ahora.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente:

  ```
  mutation addPost {
    post1: addPost(id:1 author: "AUTHORNAME" title: "A series of posts, Volume 1" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post2: addPost(id:2 author: "AUTHORNAME" title: "A series of posts, Volume 2" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post3: addPost(id:3 author: "AUTHORNAME" title: "A series of posts, Volume 3" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post4: addPost(id:4 author: "AUTHORNAME" title: "A series of posts, Volume 4" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post5: addPost(id:5 author: "AUTHORNAME" title: "A series of posts, Volume 5" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post6: addPost(id:6 author: "AUTHORNAME" title: "A series of posts, Volume 6" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post7: addPost(id:7 author: "AUTHORNAME" title: "A series of posts, Volume 7" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post8: addPost(id:8 author: "AUTHORNAME" title: "A series of posts, Volume 8" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
    post9: addPost(id:9 author: "AUTHORNAME" title: "A series of posts, Volume 9" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).

Ahora recorreremos la tabla obteniendo cinco resultados cada vez.
+ En el panel **Queries (Consultas)**, pegue la siguiente consulta:

  ```
  query allPost {
    allPost(count: 5) {
      posts {
        id
        title
      }
      nextToken
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Las cinco primeras publicaciones deben aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "allPost": {
        "posts": [
          {
            "id": "5",
            "title": "A series of posts, Volume 5"
          },
          {
            "id": "1",
            "title": "A series of posts, Volume 1"
          },
          {
            "id": "6",
            "title": "A series of posts, Volume 6"
          },
          {
            "id": "9",
            "title": "A series of posts, Volume 9"
          },
          {
            "id": "7",
            "title": "A series of posts, Volume 7"
          }
        ],
        "nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRkJEdXdUK09hcnovRGhNTGxLTGdMUEFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF6ajFodkhKU1paT1pncTRaUUNBUkNBZ2dHWnJiR1dQWGxkMDB1N0xEdGY4Z2JsbktzRjRua1VCcks3TFJLcjZBTFRMeGFwVGJZMDRqOTdKVFQyYVRwSzdzbVdtNlhWWFVCTnFIOThZTzBWZHVkdDI2RlkxMHRqMDJ2QTlyNWJTUWpTbWh6NE5UclhUMG9KZWJSQ2JJbXBlaDRSVlg0Tis0WTVCN1IwNmJQWWQzOVhsbTlUTjBkZkFYMVErVCthaXZoNE5jMk50RitxVmU3SlJ5WmpzMEFkSGduM3FWd2VrOW5oeFVVd3JlK1loUks5QkRzemdiMDlmZmFPVXpzaFZ4cVJRbC93RURlOTcrRmVJdXZNby9NZ1F6dUdNbFRyalpNR3FuYzZBRnhwa0VlZTFtR0FwVDFISElUZlluakptYklmMGUzUmcxbVlnVHVSbDh4S0trNmR0QVoraEhLVDhuNUI3VnF4bHRtSnlNUXBrZGl6KzkyL3VzNDl4OWhrMnVxSW01ZFFwMjRLNnF0dm9ZK1BpdERuQTc5djhzb0grVytYT3VuQ2NVVDY4TVZ1Wk5KYkRuSEFSSEVlaTlVNVBTelU5RGZ6d2pPdmhqWDNJMWhwdWUrWi83MDVHVjlPQUxSTGlwZWZPeTFOZFhwZTdHRDZnQW00bUJUK2c1eC9Ec3ZDbWVnSDFDVXRTdHVuU1ZFa2JpZytQRC9oMUwyRTNqSHhVQldaa28yU256WUc0cG0vV1RSWkFVZHZuQT09In0="
      }
    }
  }
  ```

Hemos obtenido cinco resultados y el valor `nextToken`, que nos permite obtener el siguiente conjunto de resultados.
+ Actualice la consulta `allPost` para incluir el valor de `nextToken` del conjunto de resultados anterior:

  ```
  query allPost {
    allPost(
      count: 5
      nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRlluNktJRWl6V0ZlR3hJOVJkaStrZUFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5cW8yUGFSZThnalFpemRCTUNBUkNBZ2dHWk1JODhUNzhIOFVUZGtpdFM2ZFluSWRyVDg4c2lkN1RjZzB2d1k3VGJTTWpSQ2U3WjY3TkUvU2I1dWNETUdDMmdmMHErSGJSL0pteGRzYzVEYnE1K3BmWEtBdU5jSENJdWNIUkJ0UHBPWVdWdCtsS2U5L1pNcWdocXhrem1RaXI1YnIvQkt6dU5hZmJCdE93NmtoM2Jna1BKM0RjWWhpMFBGbmhMVGg4TUVGSjBCcXg3RTlHR1V5N0tUS0JLZlV3RjFQZ0JRREdrNzFYQnFMK2R1S2IrVGtZZzVYMjFrc3NyQmFVTmNXZmhTeXE0ZUJHSWhqZWQ5c3VKWjBSSTc2ZnVQdlZkR3FLNENjQmxHYXhpekZnK2pKK1FneEU1SXduRTNYYU5TR0I4QUpmamR2bU1wbUk1SEdvWjlMUUswclczbG14RDRtMlBsaTNLaEVlcm9pem5zcmdINFpvcXIrN2ltRDN3QkJNd3BLbGQzNjV5Nnc4ZnMrK2FnbTFVOUlKOFFrOGd2bEgySHFROHZrZXBrMWlLdWRIQ25LaS9USnBlMk9JeEVPazVnRFlzRTRUU09HUlVJTkxYY2MvdW1WVEpBMUthV2hWTlAvdjNlSnlZQUszbWV6N2h5WHVXZ1BkTVBNWERQdTdjVnVRa3EwK3NhbGZOd2wvSUx4bHNyNDVwTEhuVFpyRWZvVlV1bXZ5S2VKY1RUU1lET05hM1NwWEd2UT09In0="
    ) {
      posts {
        id
        author
      }
      nextToken
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Las cuatro publicaciones restantes deben aparecer en el panel de resultados a la derecha del panel de consultas. No hay ningún `nextToken` en este conjunto, porque ya ha recorrido las nueve publicaciones y no quedan más. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "allPost": {
        "posts": [
          {
            "id": "2",
            "title": "A series of posts, Volume 2"
          },
          {
            "id": "3",
            "title": "A series of posts, Volume 3"
          },
          {
            "id": "4",
            "title": "A series of posts, Volume 4"
          },
          {
            "id": "8",
            "title": "A series of posts, Volume 8"
          }
        ],
        "nextToken": null
      }
    }
  }
  ```

## Configuración del allPostsBy Author Resolver (consulta de DynamoDB)
<a name="setting-up-the-allpostsbyauthor-resolver-ddb-query"></a>

Además de escanear DynamoDB para obtener todas las publicaciones, también puede consultar DynamoDB para obtener las publicaciones creadas por un autor determinado. La tabla de DynamoDB que creó anteriormente ya tiene un `GlobalSecondaryIndex` llamado `author-index` que puede utilizar con una operación `Query` de DynamoDB para recuperar todas las publicaciones creadas por un autor determinado.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Schema (Esquema)** modifique el tipo `Query` para agregar una nueva consulta `allPostsByAuthor`, de este modo:

  ```
  type Query {
      allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts!
      allPost(count: Int, nextToken: String): PaginatedPosts!
      getPost(id: ID): Post
  }
  ```

   **Nota:** aquí vuelve a usarse el tipo `PaginatedPosts` que empleamos en la consulta `allPost`.
+ Seleccione **Save**.
+ **En el panel de **tipos de datos** de la derecha, busque el campo **allPostsByAutor** recién creado en el tipo de **consulta** y, a continuación, seleccione Adjuntar.**
+ En el **menú Acción**, seleccione **Actualizar tiempo de ejecución** y, a continuación, elija **Solucionador de unidades (solo VTL)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "Query",
      "index" : "author-index",
      "query" : {
        "expression": "author = :author",
          "expressionValues" : {
            ":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author)
          }
      }
      #if( ${context.arguments.count} )
          ,"limit": $util.toJson($context.arguments.count)
      #end
      #if( ${context.arguments.nextToken} )
          ,"nextToken": "${context.arguments.nextToken}"
      #end
  }
  ```

  Al igual que el solucionador `allPost`, este solucionador tiene dos argumentos opcionales: `count`, que especifica el número máximo de elementos que se devolverá en una sola llamada, y `nextToken`, que se puede utilizar para recuperar el siguiente conjunto de resultados (el valor para `nextToken` se puede obtener en una llamada anterior).
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  {
      "posts": $utils.toJson($context.result.items)
      #if( ${context.result.nextToken} )
          ,"nextToken": $util.toJson($context.result.nextToken)
      #end
  }
  ```

   **Nota:** esta es la misma plantilla de mapeo de respuesta que usamos en el solucionador `allPost`.
+ Seleccione **Save**.

Si desea más información sobre el mapeo de solicitud `Query`, consulte la documentación de referencia de [Query](aws-appsync-resolver-mapping-template-reference-dynamodb-query.md).

### Llame a la API para consultar todas las publicaciones de un autor
<a name="call-the-api-to-query-all-posts-by-an-author"></a>

Ahora que el solucionador está configurado, AWS AppSync sabe cómo traducir una `allPostsByAuthor` mutación entrante en una operación de `Query` DynamoDB contra el índice. `author-index` Ahora puede consultar la tabla para recuperar todas las publicaciones de un autor determinado.

Sin embargo, antes de hacerlo, debemos rellenar la tabla con algunas publicaciones más, ya que por el momento todas son del mismo autor.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente:

  ```
  mutation addPost {
    post1: addPost(id:10 author: "Nadia" title: "The cutest dog in the world" content: "So cute. So very, very cute." url: "https://aws.amazon.com/appsync/" ) { author, title }
    post2: addPost(id:11 author: "Nadia" title: "Did you know...?" content: "AppSync works offline?" url: "https://aws.amazon.com/appsync/" ) { author, title }
    post3: addPost(id:12 author: "Steve" title: "I like GraphQL" content: "It's great" url: "https://aws.amazon.com/appsync/" ) { author, title }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).

Ahora consultaremos la tabla para que devuelva todas las publicaciones creadas por `Nadia`.
+ En el panel **Queries (Consultas)**, pegue la siguiente consulta:

  ```
  query allPostsByAuthor {
    allPostsByAuthor(author: "Nadia") {
      posts {
        id
        title
      }
      nextToken
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Todas las publicaciones creadas por `Nadia` deben aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "allPostsByAuthor": {
        "posts": [
          {
            "id": "10",
            "title": "The cutest dog in the world"
          },
          {
            "id": "11",
            "title": "Did you know...?"
          }
        ],
        "nextToken": null
      }
    }
  }
  ```

La paginación funciona con `Query` de igual modo que con `Scan`. Por ejemplo, vamos a buscar todas las publicaciones de `AUTHORNAME` y obtener cinco cada vez.
+ En el panel **Queries (Consultas)**, pegue la siguiente consulta:

  ```
  query allPostsByAuthor {
    allPostsByAuthor(
      author: "AUTHORNAME"
      count: 5
    ) {
      posts {
        id
        title
      }
      nextToken
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Todas las publicaciones creadas por `AUTHORNAME` deben aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "allPostsByAuthor": {
        "posts": [
          {
            "id": "6",
            "title": "A series of posts, Volume 6"
          },
          {
            "id": "4",
            "title": "A series of posts, Volume 4"
          },
          {
            "id": "2",
            "title": "A series of posts, Volume 2"
          },
          {
            "id": "7",
            "title": "A series of posts, Volume 7"
          },
          {
            "id": "1",
            "title": "A series of posts, Volume 1"
          }
        ],
        "nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ=="
      }
    }
  }
  ```
+ Actualice el argumento `nextToken` con el valor devuelto en la consulta anterior, de este modo:

  ```
  query allPostsByAuthor {
    allPostsByAuthor(
      author: "AUTHORNAME"
      count: 5
      nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ=="
    ) {
      posts {
        id
        title
      }
      nextToken
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Las demás publicaciones creadas por `AUTHORNAME` deben aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "allPostsByAuthor": {
        "posts": [
          {
            "id": "8",
            "title": "A series of posts, Volume 8"
          },
          {
            "id": "5",
            "title": "A series of posts, Volume 5"
          },
          {
            "id": "3",
            "title": "A series of posts, Volume 3"
          },
          {
            "id": "9",
            "title": "A series of posts, Volume 9"
          }
        ],
        "nextToken": null
      }
    }
  }
  ```

## Uso de conjuntos
<a name="using-sets"></a>

Hasta este punto, el `Post` tipo era un objeto plano key/value . También puede modelar objetos complejos con el AWS AppSyncDynamo solucionador de bases de datos, como conjuntos, listas y mapas.

Vamos a actualizar el tipo `Post` para incluir etiquetas. Una publicación puede tener cero o más etiquetas, que se almacenan en DynamoDB como un conjunto de cadenas. También configuraremos algunas mutaciones para añadir y eliminar etiquetas, y una nueva consulta para buscar las publicaciones con una etiqueta concreta.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Schema (Esquema)** modifique el tipo `Post` para agregar un nuevo campo `tags`, de este modo:

  ```
  type Post {
    id: ID!
    author: String
    title: String
    content: String
    url: String
    ups: Int!
    downs: Int!
    version: Int!
    tags: [String!]
  }
  ```
+ En el panel **Schema (Esquema)** modifique el tipo `Query` para agregar una nueva consulta `allPostsByTag`, de este modo:

  ```
  type Query {
    allPostsByTag(tag: String!, count: Int, nextToken: String): PaginatedPosts!
    allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts!
    allPost(count: Int, nextToken: String): PaginatedPosts!
    getPost(id: ID): Post
  }
  ```
+ En el panel **Schema (Schema)**, modifique el tipo `Mutation` para agregar las nuevas mutaciones `addTag` y `removeTag`, de este modo:

  ```
  type Mutation {
    addTag(id: ID!, tag: String!): Post
    removeTag(id: ID!, tag: String!): Post
    deletePost(id: ID!, expectedVersion: Int): Post
    upvotePost(id: ID!): Post
    downvotePost(id: ID!): Post
    updatePost(
      id: ID!,
      author: String,
      title: String,
      content: String,
      url: String,
      expectedVersion: Int!
    ): Post
    addPost(
      author: String!,
      title: String!,
      content: String!,
      url: String!
    ): Post!
  }
  ```
+ Seleccione **Save**.
+ En el panel de **tipos de datos** de la derecha, busque el campo **allPostsByEtiqueta** recién creado en el tipo de **consulta** y, a continuación, elija **Adjuntar**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "Scan",
      "filter": {
        "expression": "contains (tags, :tag)",
          "expressionValues": {
            ":tag": $util.dynamodb.toDynamoDBJson($context.arguments.tag)
          }
      }
      #if( ${context.arguments.count} )
          ,"limit": $util.toJson($context.arguments.count)
      #end
      #if( ${context.arguments.nextToken} )
          ,"nextToken": $util.toJson($context.arguments.nextToken)
      #end
  }
  ```
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  {
      "posts": $utils.toJson($context.result.items)
      #if( ${context.result.nextToken} )
          ,"nextToken": $util.toJson($context.result.nextToken)
      #end
  }
  ```
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **addTag** recién creado en el tipo **Mutation** y, a continuación, elija **Attach (Asociar)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "UpdateItem",
      "key" : {
          "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
      },
      "update" : {
          "expression" : "ADD tags :tags, version :plusOne",
          "expressionValues" : {
              ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] },
              ":plusOne" : { "N" : 1 }
          }
      }
  }
  ```
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **removeTag** recién creado en el tipo **Mutation** y, a continuación, elija **Attach (Asociar)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
      "version" : "2017-02-28",
      "operation" : "UpdateItem",
      "key" : {
          "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
      },
      "update" : {
          "expression" : "DELETE tags :tags ADD version :plusOne",
          "expressionValues" : {
              ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] },
              ":plusOne" : { "N" : 1 }
          }
      }
  }
  ```
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```
+ Seleccione **Save**.

### Llame a la API para trabajar con etiquetas
<a name="call-the-api-to-work-with-tags"></a>

Ahora que ha configurado los resolutores, AWS AppSync sabe cómo traducir las solicitudes entrantes `addTag` y las `allPostsByTag` solicitudes a `UpdateItem` DynamoDB `Scan` y a las operaciones. `removeTag`

Para probarlo, vamos a seleccionar una de las publicaciones que ha creado anteriormente. Por ejemplo, tomemos una publicación creada por `Nadia`.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la siguiente consulta:

  ```
  query allPostsByAuthor {
    allPostsByAuthor(
      author: "Nadia"
    ) {
      posts {
        id
        title
      }
      nextToken
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Todas las publicaciones creadas por Nadia deben aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "allPostsByAuthor": {
        "posts": [
          {
            "id": "10",
            "title": "The cutest dog in the world"
          },
          {
            "id": "11",
            "title": "Did you known...?"
          }
        ],
        "nextToken": null
      }
    }
  }
  ```
+ Usemos el que tiene el título `"The cutest dog in the world"`. Anote su `id`, ya que vamos a utilizarlo más adelante.

Ahora probemos a añadirle la etiqueta `dog`.
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente. También tendrá que actualizar el argumento `id` con el valor que anotó anteriormente.

  ```
  mutation addTag {
    addTag(id:10 tag: "dog") {
      id
      title
      tags
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación se actualiza con la nueva etiqueta.

  ```
  {
    "data": {
      "addTag": {
        "id": "10",
        "title": "The cutest dog in the world",
        "tags": [
          "dog"
        ]
      }
    }
  }
  ```

Puede agregar más etiquetas, de este modo:
+ Actualice la mutación para cambiar el argumento `tag` a `puppy`.

  ```
  mutation addTag {
    addTag(id:10 tag: "puppy") {
      id
      title
      tags
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación se actualiza con la nueva etiqueta.

  ```
  {
    "data": {
      "addTag": {
        "id": "10",
        "title": "The cutest dog in the world",
        "tags": [
          "dog",
          "puppy"
        ]
      }
    }
  }
  ```

También puede eliminar etiquetas:
+ En el panel **Queries (Consultas)**, pegue la mutación siguiente. También tendrá que actualizar el argumento `id` con el valor que anotó anteriormente.

  ```
  mutation removeTag {
    removeTag(id:10 tag: "puppy") {
      id
      title
      tags
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ La publicación se actualiza y la etiqueta `puppy` se elimina.

  ```
  {
    "data": {
      "addTag": {
        "id": "10",
        "title": "The cutest dog in the world",
        "tags": [
          "dog"
        ]
      }
    }
  }
  ```

También puede buscar todas las publicaciones que tengan una etiqueta:
+ En el panel **Queries (Consultas)**, pegue la siguiente consulta:

  ```
  query allPostsByTag {
    allPostsByTag(tag: "dog") {
      posts {
        id
        title
        tags
      }
      nextToken
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Se devolverán todas las publicaciones que tenga la etiqueta `dog`, de este modo:

  ```
  {
    "data": {
      "allPostsByTag": {
        "posts": [
          {
            "id": "10",
            "title": "The cutest dog in the world",
            "tags": [
              "dog",
              "puppy"
            ]
          }
        ],
        "nextToken": null
      }
    }
  }
  ```

## Uso de listas y mapas
<a name="using-lists-and-maps"></a>

Además de usar conjuntos de DynamoDB, también puede usar las listas y mapas de DynamoDB para modelar datos complejos con un único objeto.

Vamos a añadir la capacidad de agregar comentarios a las publicaciones. Esto se modelará como una lista de objetos de mapa para el objeto `Post` en DynamoDB.

 **Nota:** en una aplicación real, los comentarios se incluirían en su propia tabla. Para este tutorial, nos limitaremos a añadirlos a la tabla `Post`.
+ Elija la pestaña **Schema (Esquema)**.
+ En el panel **Schema (Esquema)**, agregue un nuevo tipo `Comment` de este modo:

  ```
  type Comment {
      author: String!
      comment: String!
  }
  ```
+ En el panel **Schema (Esquema)** modifique el tipo `Post` para agregar un nuevo campo `comments`, de este modo:

  ```
  type Post {
    id: ID!
    author: String
    title: String
    content: String
    url: String
    ups: Int!
    downs: Int!
    version: Int!
    tags: [String!]
    comments: [Comment!]
  }
  ```
+ En el panel **Schema (Esquema)** modifique el tipo `Mutation` para agregar una nueva mutación `addComment` de este modo:

  ```
  type Mutation {
    addComment(id: ID!, author: String!, comment: String!): Post
    addTag(id: ID!, tag: String!): Post
    removeTag(id: ID!, tag: String!): Post
    deletePost(id: ID!, expectedVersion: Int): Post
    upvotePost(id: ID!): Post
    downvotePost(id: ID!): Post
    updatePost(
      id: ID!,
      author: String,
      title: String,
      content: String,
      url: String,
      expectedVersion: Int!
    ): Post
    addPost(
      author: String!,
      title: String!,
      content: String!,
      url: String!
    ): Post!
  }
  ```
+ Seleccione **Save**.
+ En el panel **Data types (Tipos de datos)** de la derecha, busque el campo **addComment** recién creado en el tipo **Mutation** y, a continuación, elija **Attach (Asociar)**.
+ En **Data source name (Nombre del origen de datos)**, elija **PostDynamoDBTable**.
+ En **Configure the request mapping template (Configurar la plantilla de mapeo de solicitud)**, pegue lo siguiente:

  ```
  {
    "version" : "2017-02-28",
    "operation" : "UpdateItem",
    "key" : {
      "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
    },
    "update" : {
      "expression" : "SET comments = list_append(if_not_exists(comments, :emptyList), :newComment) ADD version :plusOne",
      "expressionValues" : {
        ":emptyList": { "L" : [] },
        ":newComment" : { "L" : [
          { "M": {
            "author": $util.dynamodb.toDynamoDBJson($context.arguments.author),
            "comment": $util.dynamodb.toDynamoDBJson($context.arguments.comment)
            }
          }
        ] },
        ":plusOne" : $util.dynamodb.toDynamoDBJson(1)
      }
    }
  }
  ```

  Esta expresión de actualización agregará una lista con nuestro nuevo comentario a la lista `comments` existente. Si la lista no existe todavía, se creará.
+ En **Configure the response mapping template (Configurar la plantilla de mapeo de respuesta)**, pegue lo siguiente:

  ```
  $utils.toJson($context.result)
  ```
+ Seleccione **Save**.

### Llame a la API para añadir un comentario
<a name="call-the-api-to-add-a-comment"></a>

Ahora que ha configurado los resolutores, AWS AppSync sabe cómo convertir las `addComment` solicitudes entrantes en operaciones de DynamoDB`UpdateItem`.

Vamos a probarlo añadiendo un comentario a la misma publicación a la que añadimos las etiquetas.
+ Seleccione la pestaña **Queries (Consultas)**.
+ En el panel **Queries (Consultas)**, pegue la siguiente consulta:

  ```
  mutation addComment {
    addComment(
      id:10
      author: "Steve"
      comment: "Such a cute dog."
    ) {
      id
      comments {
        author
        comment
      }
    }
  }
  ```
+ Elija **Execute query (Ejecutar consulta)** (el botón de reproducción naranja).
+ Todas las publicaciones creadas por Nadia deben aparecer en el panel de resultados a la derecha del panel de consultas. Debería parecerse a lo que sigue:

  ```
  {
    "data": {
      "addComment": {
        "id": "10",
        "comments": [
          {
            "author": "Steve",
            "comment": "Such a cute dog."
          }
        ]
      }
    }
  }
  ```

Si ejecuta la solicitud varias veces, se agregarán varios comentarios a la lista.

## Conclusión
<a name="conclusion"></a>

En este tutorial, ha creado una API que nos permite manipular objetos Post en DynamoDB mediante GraphQL AWS AppSync . Para obtener más información, consulte la [Referencia de plantillas de mapeo de solucionador para Elasticsearch](resolver-mapping-template-reference.md#aws-appsync-resolver-mapping-template-reference).

Para limpiar, puedes eliminar la API de AppSync GraphQL de la consola.

Para eliminar la tabla de DynamoDB y el rol de IAM que creó para este tutorial, puede ejecutar lo siguiente para eliminar la pila o visitar `AWSAppSyncTutorialForAmazonDynamoDB` la consola y eliminar CloudFormation la pila:

```
aws cloudformation delete-stack \
    --stack-name AWSAppSyncTutorialForAmazonDynamoDB
```