

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.

# Uso de AWS Lambda resolutores en AWS AppSync
<a name="tutorial-lambda-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).

Puedes usar AWS Lambda with AWS AppSync para resolver cualquier campo de GraphQL. Por ejemplo, una consulta de GraphQL podría enviar una llamada a una instancia de Amazon Relational Database Service (Amazon RDS), y una mutación de GraphQL podría escribir en un flujo de Amazon Kinesis. En esta sección, veremos cómo puede escribir una función de lambda que ejecute la lógica de negocio en función de la invocación de una operación de campo de GraphQL.

## Crear una función de Lambda
<a name="create-a-lam-function"></a>

En el siguiente ejemplo se muestra una función de Lambda escrita en `Node.js` que realiza distintas operaciones con publicaciones de blogs como parte de una aplicación de publicaciones de blog.

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    var posts = {
         "1": {"id": "1", "title": "First book", "author": "Author1", "url": "https://amazon.com/", "content": "SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1", "ups": "100", "downs": "10"},
         "2": {"id": "2", "title": "Second book", "author": "Author2", "url": "https://amazon.com", "content": "SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT", "ups": "100", "downs": "10"},
         "3": {"id": "3", "title": "Third book", "author": "Author3", "url": null, "content": null, "ups": null, "downs": null },
         "4": {"id": "4", "title": "Fourth book", "author": "Author4", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4", "ups": "1000", "downs": "0"},
         "5": {"id": "5", "title": "Fifth book", "author": "Author5", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT", "ups": "50", "downs": "0"} };

    var relatedPosts = {
        "1": [posts['4']],
        "2": [posts['3'], posts['5']],
        "3": [posts['2'], posts['1']],
        "4": [posts['2'], posts['1']],
        "5": []
    };

    console.log("Got an Invoke Request.");
    switch(event.field) {
        case "getPost":
            var id = event.arguments.id;
            callback(null, posts[id]);
            break;
        case "allPosts":
            var values = [];
            for(var d in posts){
                values.push(posts[d]);
            }
            callback(null, values);
            break;
        case "addPost":
            // return the arguments back
            callback(null, event.arguments);
            break;
        case "addPostErrorWithData":
            var id = event.arguments.id;
            var result = posts[id];
            // attached additional error information to the post
            result.errorMessage = 'Error with the mutation, data has changed';
            result.errorType = 'MUTATION_ERROR';
            callback(null, result);
            break;
        case "relatedPosts":
            var id = event.source.id;
            callback(null, relatedPosts[id]);
            break;
        default:
            callback("Unknown field, unable to resolve" + event.field, null);
            break;
    }
};
```

Esta función de Lambda recupera una publicación por identificador, añade una publicación, recupera una lista de publicaciones y recupera publicaciones relacionadas para una publicación determinada.

 **Nota:** La función de Lambda utiliza la instrucción `switch` en `event.field` para determinar qué campo se está resolviendo en ese momento.

Cree esta función Lambda mediante la consola de AWS administración o una AWS CloudFormation pila. Para crear la función a partir de una CloudFormation pila, puede utilizar el siguiente comando AWS Command Line Interface (AWS CLI):

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

También puedes lanzar la CloudFormation pila en la AWS región EE.UU. Oeste (Oregón) de tu AWS cuenta desde aquí:

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

## Configure un origen de datos para Lambda
<a name="configure-data-source-for-lamlong"></a>

Una vez creada la función de Lambda, vaya a la API de GraphQL en la consola de AWS AppSync y elija la pestaña **Orígenes de datos**.

Elija **Crear origen de datos**, introduzca un **Nombre de origen de datos** fácil de recordar (por ejemplo, **Lambda**) y, a continuación, en **Tipo de origen de datos**, elija **Función de AWS Lambda .** En **Región**, elija la misma región que en su función. (Si has creado la función a partir de la CloudFormation pila proporcionada, es probable que la función esté en **US-WEST-2**). En **ARN de función**, elija el nombre de recurso de Amazon (ARN) para la función de Lambda.

Tras elegir la función Lambda, puede crear una nueva función (de IAM) AWS Identity and Access Management (para la que se AWS AppSync asignen los permisos adecuados) o elegir una función existente que tenga la siguiente política en línea:

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

****  

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

------

También debe establecer una relación de confianza con el rol de IAM de AWS AppSync la siguiente manera:

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "appsync.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

------

## Cree un esquema de GraphQL
<a name="creating-a-graphql-schema"></a>

Ahora que el origen de datos está conectado a la función de Lambda, cree un esquema de GraphQL.

En el editor de esquemas de la AWS AppSync consola, asegúrese de que el esquema coincide con el siguiente esquema:

```
schema {
    query: Query
    mutation: Mutation
}

type Query {
    getPost(id:ID!): Post
    allPosts: [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
    relatedPosts: [Post]
}
```

## Configure solucionadores
<a name="configuring-resolvers"></a>

Ahora que ha registrado un origen de datos de Lambda y un esquema de GraphQL válido, puede conectar sus campos de GraphQL al origen de datos de Lambda utilizando solucionadores.

Para crear un solucionador, necesitará plantillas de mapeo. Para obtener más información sobre las plantillas de mapeo, consulte [Resolver Mapping Template Overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

Para obtener más información sobre las plantillas de mapeo de Lambda, consulte [Resolver mapping template reference for Lambda](resolver-mapping-template-reference-lambda.md#aws-appsync-resolver-mapping-template-reference-lambda).

En este paso, debe asociar un solucionador a la función de Lambda para los siguientes campos: `getPost(id:ID!): Post`, `allPosts: [Post]`, `addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!` y `Post.relatedPosts: [Post]`.

En el editor de esquemas de la AWS AppSync consola, en la parte derecha, selecciona **Attach Resolver** for`getPost(id:ID!): Post`.

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

Después, elija el origen de datos de Lambda. En la sección de la **plantilla de mapeo de solicitud**, elija **Invoke And Forward Argumentos (Invocar y reenviar argumentos)**.

Modifique el objeto `payload` para agregar el nombre de campo. La plantilla debe tener el aspecto siguiente:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "arguments":  $utils.toJson($context.arguments)
    }
}
```

En la sección **Plantilla de mapeo de respuestas**, elija **Devolver resultado Lambda**.

En este caso utilice la plantilla base tal y como está. Debe parecerse a lo siguiente:

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

Seleccione **Save**. Acaba de asociar su primer solucionador. Repita esta operación para el resto de los campos como se indica a continuación:

Para la plantilla de mapeo de solicitudes `addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!`:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "addPost",
        "arguments":  $utils.toJson($context.arguments)
    }
}
```

Para la plantilla de mapeo de respuestas `addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!`:

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

Para la plantilla de mapeo de solicitudes `allPosts: [Post]`:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "allPosts"
    }
}
```

Para la plantilla de mapeo de respuestas `allPosts: [Post]`:

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

Para la plantilla de mapeo de solicitudes `Post.relatedPosts: [Post]`:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "relatedPosts",
        "source":  $utils.toJson($context.source)
    }
}
```

Para la plantilla de mapeo de respuestas `Post.relatedPosts: [Post]`:

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

## Pruebe la API de GraphQL
<a name="testing-your-graphql-api"></a>

Ahora que la función de Lambda está conectada a los solucionadores de GraphQL, puede ejecutar algunas mutaciones y consultas con la consola o una aplicación cliente.

En la parte izquierda de la AWS AppSync consola, selecciona **Consultas** y, a continuación, pega el siguiente código:

### Mutación addPost
<a name="addpost-mutation"></a>

```
mutation addPost {
    addPost(
        id: 6
        author: "Author6"
        title: "Sixth book"
        url: "https://www.amazon.com/"
        content: "This is the book is a tutorial for using GraphQL with AWS AppSync."
    ) {
        id
        author
        title
        content
        url
        ups
        downs
    }
}
```

### Consulta getPost
<a name="getpost-query"></a>

```
query getPost {
    getPost(id: "2") {
        id
        author
        title
        content
        url
        ups
        downs
    }
}
```

### Consulta allPosts
<a name="allposts-query"></a>

```
query allPosts {
    allPosts {
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {
            id
            title
        }
    }
}
```

## Devolución de errores
<a name="returning-errors"></a>

Cualquier resolución de campo dada puede producir un error. Con AWS AppSync, puede generar errores de las siguientes fuentes:
+ Plantilla de mapeo de solicitudes o de respuestas
+ Función de Lambda

### Desde la plantilla de mapeo
<a name="from-the-mapping-template"></a>

Para generar errores intencionados, puede utilizar el método de ayuda `$utils.error` de la plantilla de Velocity Template Language (VTL). Indique como argumentos un mensaje en `errorMessage`, un tipo en `errorType` y un valor opcional en `data`. El argumento `data` es útil para devolver datos adicionales al cliente cuando se produce un error. El objeto `data` se añade a `errors` en la respuesta final de GraphQL.

En el siguiente ejemplo se muestra cómo usarlo en la plantilla de mapeo de respuestas `Post.relatedPosts: [Post]`:

```
$utils.error("Failed to fetch relatedPosts", "LambdaFailure", $context.result)
```

Así se obtiene una respuesta de GraphQL similar a la siguiente:

```
{
    "data": {
        "allPosts": [
            {
                "id": "2",
                "title": "Second book",
                "relatedPosts": null
            },
            ...
        ]
    },
    "errors": [
        {
            "path": [
                "allPosts",
                0,
                "relatedPosts"
            ],
            "errorType": "LambdaFailure",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ],
            "message": "Failed to fetch relatedPosts",
            "data": [
                {
                  "id": "2",
                  "title": "Second book"
                },
                {
                  "id": "1",
                  "title": "First book"
                }
            ]
        }
    ]
}
```

Donde `allPosts[0].relatedPosts` es *null* debido al error y `errorMessage`, `errorType` y `data` se incluyen en el objeto `data.errors[0]`.

### Desde la función de Lambda
<a name="from-the-lam-function"></a>

AWS AppSync también entiende los errores que arroja la función Lambda. El modelo de programación de Lambda permite generar errores *gestionados*. Si la función Lambda arroja un error, AWS AppSync no resuelve el campo actual. La respuesta solo incluirá el mensaje de error que devuelva Lambda. Actualmente no es posible devolver datos adicionales al cliente generando un error desde la función de Lambda.

 **Nota**: Si la función Lambda genera un error *no controlado*, AWS AppSync utiliza el mensaje de error establecido por Lambda.

La siguiente función de Lambda genera un error:

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    callback("I fail. Always.");
};
```

Así se obtiene una respuesta de GraphQL similar a la siguiente:

```
{
    "data": {
        "allPosts": [
            {
                "id": "2",
                "title": "Second book",
                "relatedPosts": null
            },
            ...
        ]
    },
    "errors": [
        {
            "path": [
                "allPosts",
                0,
                "relatedPosts"
            ],
            "errorType": "Lambda:Handled",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ],
            "message": "I fail. Always."
        }
    ]
}
```

## Caso de uso avanzado: agrupación en lotes
<a name="advanced-use-case-batching"></a>

La función de Lambda de este ejemplo tiene un campo `relatedPosts` que devuelve una lista de publicaciones relacionadas para una publicación determinada. En las consultas del ejemplo, la invocación al campo `allPosts` desde la función de Lambda devuelve cinco publicaciones. Dado que hemos especificado que también queremos resolver `relatedPosts` para cada publicación obtenida, la operación del campo `relatedPosts` se invoca cinco veces.

```
query allPosts {
    allPosts {   // 1 Lambda invocation - yields 5 Posts
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {   // 5 Lambda invocations - each yields 5 posts
            id
            title
        }
    }
}
```

Aunque no parezca mucho en este ejemplo concreto, esta sobrecarga compuesta puede perjudicar rápidamente a la aplicación.

Si quisiéramos obtener `relatedPosts` otra vez para todos los elementos de `Posts` en la misma consulta, el número de invocaciones aumentaría exponencialmente.

```
query allPosts {
    allPosts {   // 1 Lambda invocation - yields 5 Posts
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {   // 5 Lambda invocations - each yield 5 posts = 5 x 5 Posts
            id
            title
            relatedPosts {  // 5 x 5 Lambda invocations - each yield 5 posts = 25 x 5 Posts
                id
                title
                author
            }
        }
    }
}
```

En esta consulta relativamente simple, AWS AppSync invocaría la función Lambda 1 \$1 5 \$1 25 = 31 veces.

Se trata de una situación bastante habitual que a menudo se denomina "problema N\$11", (en nuestro caso, N = 5) y puede causar un aumento de la latencia y del costo de la aplicación.

Una forma de solucionarlo es agrupar por lotes las solicitudes de solucionador de campo similares. En este ejemplo, en lugar de hacer que la función de Lambda obtenga una lista de publicaciones relacionadas con una publicación individual determinada, hacemos que obtenga una lista de publicaciones relacionadas con un lote de publicaciones dado.

Para ilustrarlo modificaremos el solucionador `Post.relatedPosts: [Post]` de modo que utilice lotes.

En el lado derecho de la AWS AppSync consola, elija la resolución existente`Post.relatedPosts: [Post]`. Cambie la plantilla de mapeo de solicitud por lo siguiente:

```
{
    "version": "2017-02-28",
    "operation": "BatchInvoke",
    "payload": {
        "field": "relatedPosts",
        "source":  $utils.toJson($context.source)
    }
}
```

Observe que solo cambia el campo `operation` de `Invoke` a `BatchInvoke`. El campo de carga es ahora una matriz que contiene lo que especifique la plantilla. En este ejemplo, la función de Lambda recibe lo siguiente como entrada:

```
[
    {
        "field": "relatedPosts",
        "source": {
            "id": 1
        }
    },
    {
        "field": "relatedPosts",
        "source": {
            "id": 2
        }
    },
    ...
]
```

Cuando se especifica `BatchInvoke` en la plantilla de mapeo de solicitudes, la función de Lambda recibe una lista de solicitudes y devuelve una lista de resultados.

En concreto, la lista de resultados debe coincidir con el tamaño y el orden de las entradas de carga útil de la solicitud para que AWS AppSync los resultados coincidan en consecuencia.

En este ejemplo de agrupación en lotes, la función de Lambda devuelve un lote de resultados de este modo:

```
[
    [{"id":"2","title":"Second book"}, {"id":"3","title":"Third book"}],   // relatedPosts for id=1
    [{"id":"3","title":"Third book"}]                                                             // relatedPosts for id=2
]
```

La función de Lambda siguiente escrita en Node.js ilustra esta funcionalidad de agrupación en lotes para el campo `Post.relatedPosts`:

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    var posts = {
         "1": {"id": "1", "title": "First book", "author": "Author1", "url": "https://amazon.com/", "content": "SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1", "ups": "100", "downs": "10"},
         "2": {"id": "2", "title": "Second book", "author": "Author2", "url": "https://amazon.com", "content": "SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT", "ups": "100", "downs": "10"},
         "3": {"id": "3", "title": "Third book", "author": "Author3", "url": null, "content": null, "ups": null, "downs": null },
         "4": {"id": "4", "title": "Fourth book", "author": "Author4", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4", "ups": "1000", "downs": "0"},
         "5": {"id": "5", "title": "Fifth book", "author": "Author5", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT", "ups": "50", "downs": "0"} };

    var relatedPosts = {
        "1": [posts['4']],
        "2": [posts['3'], posts['5']],
        "3": [posts['2'], posts['1']],
        "4": [posts['2'], posts['1']],
        "5": []
    };

    console.log("Got a BatchInvoke Request. The payload has %d items to resolve.", event.length);
    // event is now an array
    var field = event[0].field;
    switch(field) {
        case "relatedPosts":
            var results = [];
            // the response MUST contain the same number
            // of entries as the payload array
            for (var i=0; i< event.length; i++) {
                console.log("post {}", JSON.stringify(event[i].source));
                results.push(relatedPosts[event[i].source.id]);
            }
            console.log("results {}", JSON.stringify(results));
            callback(null, results);
            break;
        default:
            callback("Unknown field, unable to resolve" + field, null);
            break;
    }
};
```

### Devolución de errores individuales
<a name="returning-individual-errors"></a>

Los ejemplos anteriores muestran cómo devolver un único error desde la función de Lambda o generar un error desde las plantillas de mapeo. En las invocaciones en lotes, la generación de un error desde la función de Lambda marca como fallido todo el lote. Esto puede ser adecuado en situaciones concretas donde se haya producido un error irrecuperable, como, por ejemplo, un error de conexión a un almacén de datos. Sin embargo, en los casos en los que algunos elementos del lote se ejecutan correctamente y otros fallan, es posible devolver tanto los errores como los datos válidos. Dado AWS AppSync que la respuesta del lote requiere que se enumeren los elementos que coincidan con el tamaño original del lote, debe definir una estructura de datos que pueda diferenciar los datos válidos de los errores.

Por ejemplo, si se espera que la función de Lambda devuelva un lote de publicaciones relacionadas, podría optar por devolver una lista de objetos `Response` en la que cada objeto tenga los campos opcionales *data*, *errorMessage* y *errorType*. Si el campo *errorMessage* está presente, significa que se ha producido un error.

El código siguiente muestra cómo podría actualizar la función de Lambda:

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    var posts = {
         "1": {"id": "1", "title": "First book", "author": "Author1", "url": "https://amazon.com/", "content": "SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1", "ups": "100", "downs": "10"},
         "2": {"id": "2", "title": "Second book", "author": "Author2", "url": "https://amazon.com", "content": "SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT", "ups": "100", "downs": "10"},
         "3": {"id": "3", "title": "Third book", "author": "Author3", "url": null, "content": null, "ups": null, "downs": null },
         "4": {"id": "4", "title": "Fourth book", "author": "Author4", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4", "ups": "1000", "downs": "0"},
         "5": {"id": "5", "title": "Fifth book", "author": "Author5", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT", "ups": "50", "downs": "0"} };

    var relatedPosts = {
        "1": [posts['4']],
        "2": [posts['3'], posts['5']],
        "3": [posts['2'], posts['1']],
        "4": [posts['2'], posts['1']],
        "5": []
    };

    console.log("Got a BatchInvoke Request. The payload has %d items to resolve.", event.length);
    // event is now an array
    var field = event[0].field;
    switch(field) {
        case "relatedPosts":
            var results = [];
            results.push({ 'data': relatedPosts['1'] });
            results.push({ 'data': relatedPosts['2'] });
            results.push({ 'data': null, 'errorMessage': 'Error Happened', 'errorType': 'ERROR' });
            results.push(null);
            results.push({ 'data': relatedPosts['3'], 'errorMessage': 'Error Happened with last result', 'errorType': 'ERROR' });
            callback(null, results);
            break;
        default:
            callback("Unknown field, unable to resolve" + field, null);
            break;
    }
};
```

En este ejemplo, la plantilla de mapeo de respuestas siguiente analiza cada elemento de la función de Lambda y genera los errores que se produzcan:

```
#if( $context.result && $context.result.errorMessage )
    $utils.error($context.result.errorMessage, $context.result.errorType, $context.result.data)
#else
    $utils.toJson($context.result.data)
#end
```

Este ejemplo devuelve una respuesta de GraphQL similar a la siguiente:

```
{
  "data": {
    "allPosts": [
      {
        "id": "1",
        "relatedPostsPartialErrors": [
          {
            "id": "4",
            "title": "Fourth book"
          }
        ]
      },
      {
        "id": "2",
        "relatedPostsPartialErrors": [
          {
            "id": "3",
            "title": "Third book"
          },
          {
            "id": "5",
            "title": "Fifth book"
          }
        ]
      },
      {
        "id": "3",
        "relatedPostsPartialErrors": null
      },
      {
        "id": "4",
        "relatedPostsPartialErrors": null
      },
      {
        "id": "5",
        "relatedPostsPartialErrors": null
      }
    ]
  },
  "errors": [
    {
      "path": [
        "allPosts",
        2,
        "relatedPostsPartialErrors"
      ],
      "errorType": "ERROR",
      "locations": [
        {
          "line": 4,
          "column": 9
        }
      ],
      "message": "Error Happened"
    },
    {
      "path": [
        "allPosts",
        4,
        "relatedPostsPartialErrors"
      ],
      "data": [
        {
          "id": "2",
          "title": "Second book"
        },
        {
          "id": "1",
          "title": "First book"
        }
      ],
      "errorType": "ERROR",
      "locations": [
        {
          "line": 4,
          "column": 9
        }
      ],
      "message": "Error Happened with last result"
    }
  ]
}
```

### Configuración del tamaño máximo de agrupación en lotes
<a name="configure-max-batch-size"></a>

De forma predeterminada, cuando se usa`BatchInvoke`, AWS AppSync envía solicitudes a la función Lambda en lotes de hasta cinco elementos. Puede configurar el tamaño máximo de lote de sus solucionadores de Lambda.

Para configurar el tamaño máximo de procesamiento por lotes en una resolución, utilice el siguiente comando en (): AWS Command Line Interface AWS CLI

```
$ aws appsync create-resolver --api-id <api-id> --type-name Query --field-name relatedPosts \
 --request-mapping-template "<template>" --response-mapping-template "<template>" --data-source-name "<lambda-datasource>" \ 
 --max-batch-size X
```

**nota**  
Al proporcionar una plantilla de mapeo de solicitudes, debe usar la operación `BatchInvoke` para usar la agrupación en lotes.

También puede utilizar el siguiente comando para habilitar y configurar la agrupación en lotes en solucionadores de Direct Lambda:

```
$ aws appsync create-resolver --api-id <api-id> --type-name Query --field-name relatedPosts \
 --data-source-name "<lambda-datasource>" \ 
 --max-batch-size X
```

### Configuración del tamaño máximo de agrupación en lotes con plantillas de VTL
<a name="configure-max-batch-size-vtl"></a>

Para los solucionadores de Lambda que tienen plantillas en solicitudes de VTL, el tamaño máximo del lote no tendrá ningún efecto a menos que lo hayan especificado directamente como una operación `BatchInvoke` en VTL. Del mismo modo, si realiza una mutación de nivel superior, no se realiza la agrupación en lotes de las mutaciones porque la especificación GraphQL requiere que las mutaciones paralelas se ejecuten secuencialmente.

Por ejemplo, tomemos las mutaciones siguientes:

```
type Mutation {
    putItem(input: Item): Item
    putItems(inputs: [Item]): [Item]
}
```

Con la primera mutación, podemos crear 10 `Items`, como se muestra en el siguiente fragmento:

```
mutation MyMutation {
    v1: putItem($someItem1) {
        id,
        name
    }
    v2: putItem($someItem2) {
        id,
        name
    }
    v3: putItem($someItem3) {
        id,
        name
    } 
    v4: putItem($someItem4) {
        id,
        name
    }
    v5: putItem($someItem5) {
        id,
        name
    }
    v6: putItem($someItem6) {
        id,
        name
    } 
    v7: putItem($someItem7) {
        id,
        name
    }
    v8: putItem($someItem8) {
        id,
        name
    }
    v9: putItem($someItem9) {
        id,
        name
    }
    v10: putItem($someItem10) {
        id,
        name
    }
}
```

En este ejemplo, los `Items` no se agruparán en un grupo de 10 aunque el tamaño máximo del lote esté establecido en 10 en el solucionador de Lambda. En su lugar, se ejecutarán secuencialmente de acuerdo con la especificación GraphQL.

Para realizar una mutación por lotes real, puede seguir el siguiente ejemplo utilizando la segunda mutación:

```
mutation MyMutation {
    putItems([$someItem1, $someItem2, $someItem3,$someItem4, $someItem5, $someItem6, 
    $someItem7, $someItem8, $someItem9, $someItem10]) {
    id,
    name
    }
}
```

Para obtener más información sobre el uso de agrupaciones en lotes con solucionadores de Direct Lambda, consulte [Solucionadores de Lambda directos](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers).