Ordered association for Ecto/Absinthe

Hello everyone,

I am trying to order an ecto association by a given column. But as seen on this old ecto issue this does not seem possible, instead, it’s possible to preload with order.

I have games, with many nodes. I would like to sort the nodes association by the index column.

My Game schema is

  schema "games" do
    ...
    has_many :nodes, Node
    
    timestamps()
  end

and here my node schema

  @primary_key false
  schema "nodes" do
    belongs_to :game, Game
    field :index, :integer, primary_key: true
    ...    
    timestamps()
  end

The problem I am having is with Absinthe, because I am using the association to resolve the list of nodes belonging to a game. But they are not ordered like I would… by the index column…

in the Schema.Types

    # Has_many
    @desc "List of nodes"
    field :nodes, list_of(:node), resolve: assoc(:nodes)

Is it possible to use something like this?

has_many :nodes, Node, order_by: :index

or is it possible to use something like that?

field :nodes, list_of(:node), resolve: specific_resolver_function_with_ordered_nodes_inside

Thanks for taking time

I don’t think you can add sorts to existing assoc helper. A couple of suggestions

1.) Add a middleware after your resolver to sort the returned results

field :nodes, list_of(:node) do
 resolve assoc(:nodes)
 middleware &node_sorter/2
end

2.) Write your own custom batch method instead of using the assoc helper. There’s an example in the Absinthe Docs

1 Like

@law Thank You for your suggestion, I will have a look to the mentionned docs, and see if I can make it work.

Hey!

This has been in absinthe_ecto master for a while but I just released it. You can do

field :nodes, list_of(:node), resolve: assoc(:nodes, fn nodes_query ->
  nodes_query |> order_by(asc: :index)
end)

The function you can pass to assoc gets the base ecto query, and you can add stuff on top of that.

https://hexdocs.pm/absinthe_ecto/Absinthe.Ecto.html#assoc/2

6 Likes

Thank You @benwilson512 for your answer and your awesome work on Absinthe :slight_smile:

1 Like

BTW The exact syntax I used to make it work is

field :nodes, list_of(:node), resolve: assoc(:nodes, fn query, _, _ -> 
  query |> order_by(asc: :index)
end)
2 Likes

oops! good catch, docs updated. The second argument is the args, and the last argument is the context FYI

1 Like

Is this still supported in Absinthe v1.4.x? I see it still in the docs but when I tried to do the same thing in my code, it still returns the assoc unsorted in the JSON response.

For example:

field(
  :foobars,
  list_of(:foobar),
  resolve:
    assoc(:foobars, fn query, _args, _context ->
      query |> order_by(desc: :inserted_at)
    end)
)
1 Like

The assoc helpers have been largely deprecated in favor of dataloader. Nothing in Absinthe itself should affect whether that works though.

1 Like