nallwhy
How to properly use aggregates on a resource?
I’m a bit stuck on how to correctly use aggregates on a resource.
Let’s say I have the following resource:
defmodule MyApp.Invoice do
use Ash.Resource
attributes do
uuid_v7_primary_key :id
attribute :amount, :decimal, allow_nil?: false
attribute :settled, :boolean, default: false, allow_nil?: false
end
end
I want to get the sum of all amounts where `settled is false, so I defined this aggregate:
aggregates do
sum :total_amount, [], :amount do
filter expr(not settled)
end
end
But:
- I’m not sure what the proper way to fetch this aggregate is.
- When I tried using
Ash.aggregate(MyApp.Invoice, {:total_amount, :sum}), it didn’t seem to apply the filter.
I’m not sure if this is a bug or if I’m misunderstanding how it’s supposed to work.
I only shared the relevant code here, but if it helps, I can create a minimal repo to reproduce it.
Thanks in advance!
Marked As Solved
zachdaniel
Ash.aggregate(Resource, {:total_amount, :sum}) should be requiring that you specify a field to be summing, i.e Ash.aggregate(Resource, {:total_amount, :sum, field: :amount}).
Ash.aggregate is for aggregating information about a query/resource as a whole. i.e
Resource
|> Ash.Query.filter(not settled)
|> Ash.aggregate(Resource, {:total_amount, :sum, field: :amount}
will get you back something like this:
{:ok, %{total_amount: #Decimal<10.0>}}, and is the “sum of of all amounts that are not settled”.
The aggregates declared in a resource are different, they are more like a calculation. They are for summary information about related data.
# on a customer resource for example
sum :total_unsettled_invoices_amount, [:invoices], :total_amount do
filter expr(not settled)
end
This allows you to say:
customer |> Ash.load!(:total_unsettled_invoices_amount)
which return something like
%Customer{total_unsettled_invoices_amount: #Decimal<10.0>}
That total_invoices_amount is “for the given customer(s), the sum of all related invoices, which are not settled”
Hopefully that helps!
Also Liked
FlyingNoodle
Aggregates are “per instance of this resource”.
I think something like this:
# in your resource
defmodule MyApp.Invoice do
actions do
read :not_settled do
filter expr(not settled)
end
end
end
# in your domain
defmodule MyApp.MyDomain do
resource MyApp.Invoice do
read :get_not_settled_invoices, action: :not_settled
end
end
# consumer
MyApp.MyDomain.get_not_settled_invoices() |> Ash.sum(:amount)
but I don’t know if thats the best way to do it? I mean you can also put this function in your domain or wherever you like.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









