How can I setup the schema for self-referencing association?

I have a self-referencing model, and I was able to get it to work with the following. However, this leads to 2 different cached objects in Apollo. Ex, ChildCategory:[id] and Category:[Id]. I would like to have a single source of truth so it makes optimistic updates more manageable.

object :child_category do
  field :id, :id
  field :name, :string
  field :category_id, :id
end

object :category do
  field :id, :id
  field :name, :string
  field :categories, list_of(:child_category), resolve: dataloader(DataloaderQueries, :categories)
end

I tried this, but it leads to an error saying it can’t query the categoryId on category. I also don’t want there to be infinite recursion. I want the second level of categories to exclude the key categories.

object :category do
  field :id, :id
  field :name, :string
  field :categories, list_of(:category), resolve: dataloader(DataloaderQueries, :categories)
end

Can you show your Category ecto schema?

Here it is:

schema "categories" do
  field :name, :string
  belongs_to :category, Categories.Category, on_replace: :mark_as_invalid
  has_many :categories, Categories.Category, foreign_key: :category_id

  timestamps()
end

OK, and if you do Repo.preload(category, [:categories]) does that work or do you get an error?

Also, can you copy / paste the full error you get when you do:

object :category do
  field :id, :id
  field :name, :string
  field :categories, list_of(:category), resolve: dataloader(DataloaderQueries, :categories)
end

Because this should work.

I get the error when I try to query with this document (I removed parts of it for brevity):

Cannot query field \"categoryId\" on type \"Category\"."

query posts($id: ID!) {
  categories {
    ...CategoryFields
    __typename
  }
}

fragment CategoryFields on Category {
  id
  name
  categories {
    id
    name
    categoryId
    __typename
  }
  __typename
}

I figured it out. I needed to add category_id here:


object :category do
  field :id, :id
  field :name, :string
  field :category_id, :id
  field :categories, list_of(:category), resolve: dataloader(DataloaderQueries, :categories)
end

Yeah, Absinthe doesn’t implicitly add id fields like ecto does, because they don’t always. make sense to add.

1 Like

Thanks for taking the time to reply and help! It’s a big reason why I love Absinthe.

1 Like