Search⌘ K
AI Features

Abstract Type Union

Explore how to define and implement abstract union types in Absinthe GraphQL schemas to combine different object types like menu items and categories. Understand how to write resolvers that determine concrete types dynamically, use fragments for precise querying, and leverage GraphQL introspection for enhanced query results.

Using unions

A GraphQL union type is an abstract type that represents a set of specific concrete types. For instance, in our PlateSlate search example, a :search_result could be a union type for both :menu_item and :category. Let’s define that in our schema. However, first, we need to add the :category type. It’s a straightforward grouping of :menu_item records with a name and description:

alias PlateSlateWeb.Resolvers
object :category do
field :name, :string
field :description, :string
field :items, list_of(:menu_item) do
resolve &Resolvers.Menu.items_for_category/3
end
end

We’ve included a resolver to load the menu items for a category when the :items field is selected. At the moment, the implementation is a bit naive:

def items_for_category(category, _, _) do
query = Ecto.assoc(category, :items)
{:ok, PlateSlate.Repo.all(query)}
end

This is the first resolver we’ve written using the first argument which receives the parent value. In our case, this resolver is on the :items field of the :category object, so its parent value is a category. We can then use that category to do a database query for its items. Let’s define the :search_result union type in menu_types.ex:

union :search_result do
types [:menu_item, :category]
#<<almost done...>>
end

This uses a couple of new macros from Absinthe. The union macro creates our type, and works a lot like an object. The types macro, used inside the union ...