Introducción

En GraphQL, las uniones (unions) son una forma poderosa de definir un tipo que puede ser uno de varios tipos diferentes. Esto es útil cuando tienes un campo que puede devolver diferentes tipos de objetos y quieres que tu esquema sea flexible y expresivo.

Conceptos Clave

  • Definición de Uniones: Una unión es un tipo especial en GraphQL que permite que un campo pueda retornar uno de varios tipos posibles.
  • Uso de Uniones: Las uniones se utilizan cuando un campo puede devolver diferentes tipos de objetos que no comparten una interfaz común.
  • Resolución de Uniones: Los resolvers deben ser capaces de determinar qué tipo de objeto se está devolviendo para una unión.

Definición de Uniones

Para definir una unión en GraphQL, utilizamos la palabra clave union seguida del nombre de la unión y los tipos que puede incluir. Aquí hay un ejemplo básico:

union SearchResult = User | Post | Comment

En este ejemplo, SearchResult es una unión que puede ser un User, un Post o un Comment.

Ejemplo Práctico

Supongamos que estamos construyendo una API para una red social y queremos implementar una búsqueda que pueda devolver usuarios, publicaciones o comentarios. Primero, definimos los tipos:

type User {
  id: ID!
  name: String!
}

type Post {
  id: ID!
  title: String!
  content: String!
}

type Comment {
  id: ID!
  text: String!
  author: User!
}

Luego, definimos la unión:

union SearchResult = User | Post | Comment

Finalmente, definimos una consulta que utiliza esta unión:

type Query {
  search(term: String!): [SearchResult!]!
}

Resolver para Uniones

Cuando se utiliza una unión, el resolver debe ser capaz de determinar el tipo de objeto que se está devolviendo. Aquí hay un ejemplo de cómo se puede implementar esto en JavaScript utilizando Apollo Server:

const { ApolloServer, gql } = require('apollo-server');

// Definición del esquema
const typeDefs = gql`
  type User {
    id: ID!
    name: String!
  }

  type Post {
    id: ID!
    title: String!
    content: String!
  }

  type Comment {
    id: ID!
    text: String!
    author: User!
  }

  union SearchResult = User | Post | Comment

  type Query {
    search(term: String!): [SearchResult!]!
  }
`;

// Datos de ejemplo
const users = [
  { id: '1', name: 'Alice' },
  { id: '2', name: 'Bob' },
];

const posts = [
  { id: '1', title: 'GraphQL Rocks', content: 'GraphQL is awesome!' },
  { id: '2', title: 'Apollo Server', content: 'Apollo Server is great!' },
];

const comments = [
  { id: '1', text: 'Great post!', author: users[0] },
  { id: '2', text: 'Very informative.', author: users[1] },
];

// Resolver
const resolvers = {
  Query: {
    search: (parent, args) => {
      const term = args.term.toLowerCase();
      const userResults = users.filter(user => user.name.toLowerCase().includes(term));
      const postResults = posts.filter(post => post.title.toLowerCase().includes(term));
      const commentResults = comments.filter(comment => comment.text.toLowerCase().includes(term));
      return [...userResults, ...postResults, ...commentResults];
    },
  },
  SearchResult: {
    __resolveType(obj) {
      if (obj.name) {
        return 'User';
      }
      if (obj.title) {
        return 'Post';
      }
      if (obj.text) {
        return 'Comment';
      }
      return null;
    },
  },
};

// Creación del servidor
const server = new ApolloServer({ typeDefs, resolvers });

// Inicio del servidor
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

Ejercicio Práctico

Ejercicio

  1. Define una unión llamada Content que pueda ser un Article o un Video.
  2. Crea los tipos Article y Video con los siguientes campos:
    • Article: id, title, body
    • Video: id, title, url
  3. Define una consulta llamada getContent que devuelva una lista de Content.
  4. Implementa los resolvers necesarios para manejar la unión Content.

Solución

# Definición del esquema
type Article {
  id: ID!
  title: String!
  body: String!
}

type Video {
  id: ID!
  title: String!
  url: String!
}

union Content = Article | Video

type Query {
  getContent: [Content!]!
}
// Datos de ejemplo
const articles = [
  { id: '1', title: 'GraphQL Tutorial', body: 'Learn GraphQL step by step.' },
  { id: '2', title: 'Advanced GraphQL', body: 'Deep dive into GraphQL.' },
];

const videos = [
  { id: '1', title: 'GraphQL Basics', url: 'http://example.com/graphql-basics' },
  { id: '2', title: 'GraphQL Advanced', url: 'http://example.com/graphql-advanced' },
];

// Resolver
const resolvers = {
  Query: {
    getContent: () => {
      return [...articles, ...videos];
    },
  },
  Content: {
    __resolveType(obj) {
      if (obj.body) {
        return 'Article';
      }
      if (obj.url) {
        return 'Video';
      }
      return null;
    },
  },
};

// Creación del servidor
const server = new ApolloServer({ typeDefs, resolvers });

// Inicio del servidor
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

Conclusión

Las uniones en GraphQL son una herramienta poderosa para manejar tipos de datos flexibles y variados. Permiten que un campo pueda devolver diferentes tipos de objetos, lo que hace que tu API sea más expresiva y adaptable a diferentes necesidades. Asegúrate de definir claramente los tipos que pueden formar parte de una unión y de implementar resolvers que puedan determinar correctamente el tipo de objeto que se está devolviendo.

© Copyright 2024. Todos los derechos reservados