Customize the association data with a callback similar to `run_batch/5`?
thojanssens opened this issue · 3 comments
run_batch/5
doesn't run for repo calls to load associations. In my case, I use the viewer pattern where everything is preloaded from the current user.
I want to alter the results of the associated data, i.e. to handle cursor-based pagination on a list.
In the Absinthe schema:
query do
field :me, :user do
resolve &Resolvers.Accounts.me/3
end
end
def dataloader() do
Dataloader.new()
|> Dataloader.add_source(Business, Business.data())
|> Dataloader.add_source(Transactions, Transactions.data())
end
def context(ctx) do
Map.put(ctx, :loader, dataloader())
end
defmodule MyAppWeb.GraphQL.Resolvers.Accounts do
def me(_, _, %{context: %{current_user: current_user}}) do
{:ok, current_user}
end
def me(_, _, _) do
{:ok, nil}
end
end
object :user do
field :id, non_null(:id)
field :name, :string
field :organizations, non_null(list_of(non_null(:organization))), resolve: dataloader(Business)
end
object :organization do
field :id, non_null(:id)
field :name, non_null(:string)
field :pagninated_revenues, :pagninated_revenues do # <- this is what I would like to achieve
arg :pagination, :pagination_input
resolve dataloader(Transactions, :revenues) # <- customize the repo call in order to include the limit and cursor metadata (return :pagninated_revenues object)
end
end
object :pagninated_revenues do
field :pagination, non_null(:pagination) # holding cursor metadata
field :revenues, non_null(list_of(non_null(:revenue)))
end
In my contexts I have the following:
def data() do
Dataloader.Ecto.new(Repo, query: &query/2, run_batch: &run_batch/5)
end
def run_batch(queryable, query, col, inputs, repo_opts) do
IO.inspect "=== run_batch ===" # <- never printed
Dataloader.Ecto.run_batch(Repo, queryable, query, col, inputs, repo_opts)
end
def query(queryable, _) do
IO.inspect "=== query ==="
queryable
end
Maybe my questioning sounds like the following discussion: #87, where I want to customize the resulting records of an association (I need to paginate). I still need to batch, where for example a user may have multiple organizations, and thus the paginated revenues can be from multiple organizations.
Hey @thojanssens the pagination input can be applied via query
, you don't need to do so via the association.
At this time I'm not really sure how I'd even enable run_batch
to work with associations. The associations rely ultimately on calling Repo.preload
and that just has a totally different set of inputs and outputs from the current run_batch
function.
Thank you so much for your help and this lib Ben!
I am closing this issue for now. Also don't understand how run_batch/5 could be executed on the query level in an Absinthe context. I understand how it works on the associations, but not on the queryable.
Hey @thojanssens what I mean by query/2
is that you can do this:
def query(Revenue, args) do
Revenue
|> maybe_add_pagination(args)
end
where maybe_add_pagination
applies an order, limit, and so forth based on the args passed in. This will be applied whether using the association or queryable.