Uso de solucionadores de Amazon OpenSearch Service en AWS AppSync - AWS AppSync GraphQL

Uso de solucionadores de Amazon OpenSearch Service en AWS AppSync

AWS AppSync admite el uso de Amazon OpenSearch Service desde dominios que ha aprovisionado en su cuenta de AWS, siempre que no se encuentren dentro de una VPC. Después de aprovisionar los dominios, puede conectarse a ellos con un origen de datos. En ese momento, puede configurar un solucionador en el esquema para que realice operaciones de GraphQL como consultas, mutaciones y suscripciones. Este tutorial le guiará a lo largo de algunos ejemplos comunes.

Para obtener más información, consulte JavaScript resolver function reference for OpenSearch.

Cree un nuevo dominio de OpenSearch Service

Para comenzar este tutorial, es necesario disponer de un dominio de OpenSearch Service. Si todavía no tiene uno, puede utilizar la siguiente muestra. Tenga en cuenta que crear un dominio de OpenSearch Service puede tardar hasta 15 minutos, por lo que deberá esperar para poder integrarlo con un origen de datos de AWS AppSync.

aws cloudformation create-stack --stack-name AppSyncOpenSearch \ --template-url https://s3.us-west-2.amazonaws.com/awsappsync/resources/elasticsearch/ESResolverCFTemplate.yaml \ --parameters ParameterKey=OSDomainName,ParameterValue=ddtestdomain ParameterKey=Tier,ParameterValue=development \ --capabilities CAPABILITY_NAMED_IAM

Como alternativa, puede iniciar la siguiente pila de AWS CloudFormation en la región EE. UU. Oeste 2 (Oregón) de su cuenta de AWS:

Blue button labeled "Launch Stack" with an arrow icon indicating an action to start.

Configure un origen de datos para OpenSearch Service

Después de crear el dominio de OpenSearch Service, vaya a la API de GraphQL para AWS AppSync y elija la pestaña Orígenes de datos. Seleccione Crear origen de datos e introduzca un nombre fácil de recordar para el origen de datos, como "oss". A continuación, elija Dominio de Amazon OpenSearch en Tipo de origen de datos y elija la región que corresponda. En la lista debe aparecer el dominio de OpenSearch Service. Una vez seleccionado, puede crear un nuevo rol y AWS AppSync le asignará los permisos adecuados. También puede elegir un rol existente que tenga la siguiente política en línea:

También debe configurar una relación de confianza con AWS AppSync para ese rol:

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

Además, el dominio de OpenSearch Service tiene su propia política de acceso, que puede modificar en la consola de Amazon OpenSearch Service. Debe añadir una política similar a la que aparece a continuación, con las acciones y recursos adecuados para el dominio de OpenSearch Service. Tenga en cuenta que el Principal será el rol del origen de datos de AWS AppSync que, si deja que la consola lo cree, podrá encontrar en la consola de IAM.

Conexión de un solucionador

Ahora que el origen de datos está conectado a su dominio de OpenSearch Service, puede conectarlo también al esquema de GraphQL con un solucionador, como se muestra en el ejemplo siguiente:

type Query { getPost(id: ID!): Post allPosts: [Post] } type Mutation { addPost(id: ID!, author: String, title: String, url: String, ups: Int, downs: Int, content: String): AWSJSON } type Post { id: ID! author: String title: String url: String ups: Int downs: Int content: String }

Observe que hay un tipo Post definido por el usuario con un campo id. En los siguientes ejemplos, supondremos que existe un proceso (que se puede automatizar) para incluir este tipo en el dominio de OpenSearch Service, lo que lo mapea a la ruta raíz de /post/_doc, donde post es el índice. A partir de esta ruta raíz, puede realizar búsquedas de documentos individuales, búsquedas de comodín con /id/post* o búsquedas en varios documentos con la ruta /post/_search. Por ejemplo, si tiene otro tipo llamado User, puede indexar documentos bajo un nuevo índice llamado user, y luego realizar búsquedas con una ruta de /user/_search.

En el editor Esquema de la consola de AWS AppSync, modifique el esquema Posts anterior para que incluya una consulta searchPosts:

type Query { getPost(id: ID!): Post allPosts: [Post] searchPosts: [Post] }

Guarde el esquema. En el panel Solucionadores, busque searchPosts y seleccione Asociar. Elija el origen de datos de OpenSearch Service y guarde el solucionador. Actualice el código del solucionador mediante el siguiente fragmento:

import { util } from '@aws-appsync/utils' /** * Searches for documents by using an input term * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the request */ export function request(ctx) { return { operation: 'GET', path: `/post/_search`, params: { body: { from: 0, size: 50 } }, } } /** * Returns the fetched items * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the result */ export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type) } return ctx.result.hits.hits.map((hit) => hit._source) }

Esto supone que el esquema anterior contiene documentos que se han indexado en OpenSearch Service en el campo post. Si estructura los datos de manera diferente, tendrá que realizar una actualización como corresponda.

Modificación de las búsquedas

El controlador de solicitudes del solucionador anterior realiza una consulta sencilla para todos los registros. Supongamos que desea buscar por un autor específico. Además, supongamos que desea que ese autor sea un argumento definido en la consulta de GraphQL. En el editor Esquema de la consola de AWS AppSync, añada una consulta allPostsByAuthor:

type Query { getPost(id: ID!): Post allPosts: [Post] allPostsByAuthor(author: String!): [Post] searchPosts: [Post] }

En el panel Solucionadores, busque allPostsByAuthor y seleccione Asociar. Elija el origen de datos de OpenSearch Service y utilice el código siguiente:

import { util } from '@aws-appsync/utils' /** * Searches for documents by `author` * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the request */ export function request(ctx) { return { operation: 'GET', path: '/post/_search', params: { body: { from: 0, size: 50, query: { match: { author: ctx.args.author } }, }, }, } } /** * Returns the fetched items * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the result */ export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type) } return ctx.result.hits.hits.map((hit) => hit._source) }

Observe que body se llena con una consulta de término para el campo author, que se pasa desde el cliente como un argumento. Si lo desea, puede usar información previamente rellenada, como texto estándar.

Adición de datos a OpenSearch Service

Puede ser conveniente añadir datos al dominio de OpenSearch Service como resultado de una mutación de GraphQL. Se trata de un eficaz mecanismo para realizar búsquedas y para otros fines. Dado que puede utilizar suscripciones de GraphQL para que los datos se obtengan en tiempo real, esto puede servir como mecanismo para avisar a los clientes de actualizaciones de datos en el dominio de OpenSearch Service.

Vuelva a la página Esquema de la consola de AWS y seleccione Asociar para la mutación addPost(). Seleccione de nuevo el origen de datos de OpenSearch Service y utilice el código siguiente:

import { util } from '@aws-appsync/utils' /** * Searches for documents by `author` * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the request */ export function request(ctx) { return { operation: 'PUT', path: `/post/_doc/${ctx.args.id}`, params: { body: ctx.args }, } } /** * Returns the inserted post * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the result */ export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type) } return ctx.result }

Como antes, este es un ejemplo de cómo pueden estar estructurados los datos. Si los nombres de campos o índices son distintos, debe actualizar la path y body. En este ejemplo, también se muestra cómo utilizar context.arguments, que también se puede escribir como ctx.args, en el controlador de solicitudes.

Recuperación de un solo documento

Por último, si desea utilizar la consulta getPost(id:ID) en su esquema para obtener un documento individual, encuentre esta consulta en el editor Esquema de la consola de AWS AppSync y seleccione Asociar. Seleccione de nuevo el origen de datos de OpenSearch Service y utilice el código siguiente:

import { util } from '@aws-appsync/utils' /** * Searches for documents by `author` * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the request */ export function request(ctx) { return { operation: 'GET', path: `/post/_doc/${ctx.args.id}`, } } /** * Returns the post * @param {import('@aws-appsync/utils').Context} ctx the context * @returns {*} the result */ export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type) } return ctx.result._source }

Ejecución de consultas y mutaciones

Ahora puede realizar operaciones de GraphQL referidas al dominio de OpenSearch Service. Vaya a la pestaña Consultas de la consola de AWS y añada un nuevo registro:

mutation AddPost { addPost ( id:"12345" author: "Fred" title: "My first book" content: "This will be fun to write!" url: "publisher website", ups: 100, downs:20 ) }

Verá el resultado de la mutación a la derecha. Del mismo modo, ahora puede ejecutar una consulta searchPosts en el dominio de OpenSearch Service:

query search { searchPosts { id title author content } }

Prácticas recomendadas

  • OpenSearch Service se debe utilizar para consultar datos, no como base de datos principal. Puede ser útil emplear OpenSearch Service junto con Amazon DynamoDB como se indica en Combinación de solucionadores de GraphQL.

  • Solo debe conceder acceso al dominio permitiendo que el rol de servicio de AWS AppSync tenga acceso al clúster.

  • Puede comenzar con un pequeño desarrollo, con el clúster de menor costo y, a continuación, pasar a un clúster de mayor tamaño con alta disponibilidad (HA) al pasar a producción.