How best to create group_by aggregates on a resource - with no relationships

Once again I am stumped and unable to find a workable solution to a problem!

I want to be able to use a count / group_by query on an Ash resource.

A viable and workable Ecto query would be:

q = Workitem |> group_by([wi], wi.status) |> select([p], [p.status, count(p.id)])

I have tried to use the above query as a “manual” read action, but am stuck being unable to fine tune the select clause of the query. I realize that I can use “prepare build(select: […])” to limit the columns being selected, but that will clash with the select part of the Ecto query as only one select part is allowed (obviously).

I also want to ensure that these results can be provided over the ash_json_api interface - hence my desire to keep it in an action.

The custom read action is:

    read :foo do
      prepare build(select: [:status])
      # prepare build(aggregate: expr(count(id))) - doesn't work!

      manual fn ash_query, ecto_query, _context ->
        IO.inspect({:ash_query, ash_query})
        IO.inspect({:ecto_query, ecto_query})

        q =
          ecto_query
          |> group_by([wi], [wi.status])
          # |> select([p], [p.status, count(p.id)])

        try do
          results = DispatchData.Repo.all(q)
          {:ok, results}
        rescue
          e ->
            {:error, e}
        end
      end
    end

Is there a workable way of achieving this. I initially reached for “aggregates” but there aren’t any related resources involved, so I took heed of the “escape hatch” paragraphs and thought a manual read the best approach.

What am I missing?

Still loving the productivity of this framework!

Martin

My suggestion is to create a generic action instead of a manual read. A manual read is still meant to return a list of records, not a custom arbitrary result.

action :count_things_by_status, :map do
  run fn input, _ -> 
    # do whatever Ecto stuff you want, and return `{:ok, the_map}`
  end
end