Calculate aggregations?

I want to sum_1 = sum_some_data(user_1, :column_1), sum_2 = sum_some_data(user_1, :column_2) then sum_1 - sum_2 and return this value.
9 Replies
ZachDaniel
ZachDaniel•3y ago
Can you provide a concrete example of the kind of data this might be? like for each user, its the sum of some related value?
dj_goku
dj_gokuOP•3y ago
defmodule Mod.OneOnOne do
use Ash.Resource,
data_layer: AshPostgres.DataLayer

postgres do
table("one_on_one")
repo(Mod.Repo)
end

actions do
defaults([:create, :read, :update, :destroy])

update :assign do
accept([])

argument :user_1_id, :uuid do
allow_nil?(false)
end

argument :user_2_id, :uuid do
allow_nil?(false)
end

# change(manage_relationship(:user_1_id, :user, type: :append_and_remove))
# change(manage_relationship(:user_2_id, :user, type: :append_and_remove))
end
end

attributes do
uuid_primary_key(:id)
end

relationships do
belongs_to :user_1_id, User
belongs_to :user_2_id, User
end
end
defmodule Mod.OneOnOne do
use Ash.Resource,
data_layer: AshPostgres.DataLayer

postgres do
table("one_on_one")
repo(Mod.Repo)
end

actions do
defaults([:create, :read, :update, :destroy])

update :assign do
accept([])

argument :user_1_id, :uuid do
allow_nil?(false)
end

argument :user_2_id, :uuid do
allow_nil?(false)
end

# change(manage_relationship(:user_1_id, :user, type: :append_and_remove))
# change(manage_relationship(:user_2_id, :user, type: :append_and_remove))
end
end

attributes do
uuid_primary_key(:id)
end

relationships do
belongs_to :user_1_id, User
belongs_to :user_2_id, User
end
end
sum_one_on_one(user_1, :user_1_id) - sum_one_on_one(user_1, :user_2_id)
ZachDaniel
ZachDaniel•3y ago
So sum_one_on_onein this case, would do something like be the count of users that a person is connected to?
dj_goku
dj_gokuOP•3y ago
It is summing how many one_on_one where they were :user_1_id and subtracting that from the sum of one_on_one where they were :user_2_id
ZachDaniel
ZachDaniel•3y ago
relationships do
has_many :user_1_one_on_ones, Mod.OneOnOne do
destination_attribute :user_1_id
end

has_many :user_2_one_on_ones, Mod.OneOnOne do
destination_attribute :user_2_id
end
end

aggregates do
count :count_of_user_1_one_on_ones, :user_1_one_on_ones
count :count_of_user_2_one_on_ones, :user_2_one_on_ones
end

calculations do
calculate :whatever_this_is_called, :integer, expr(count_of_user_1_one_on_ones - count_of_user_2_one_on_ones)
end
relationships do
has_many :user_1_one_on_ones, Mod.OneOnOne do
destination_attribute :user_1_id
end

has_many :user_2_one_on_ones, Mod.OneOnOne do
destination_attribute :user_2_id
end
end

aggregates do
count :count_of_user_1_one_on_ones, :user_1_one_on_ones
count :count_of_user_2_one_on_ones, :user_2_one_on_ones
end

calculations do
calculate :whatever_this_is_called, :integer, expr(count_of_user_1_one_on_ones - count_of_user_2_one_on_ones)
end
šŸŖ„ :magic_sparkles:
dj_goku
dj_gokuOP•3y ago
AHHH expr(count_of_user_1_one_on_ones - count_of_user_2_one_on_ones) Well it is the combination of the aggregates and calculation!
ZachDaniel
ZachDaniel•3y ago
Yep šŸ™‚ The equivalent "manual" calculation would look like this:
defmodule YourCalc do
use Ash.Calculation

def load(_, _, _) do
[:count_of_user_1_one_on_ones, :count_of_user_2_one_on_ones]
end

def calculate(users, _, _) do
{:ok, Enum.map(users, fn user ->
user.count_of_user_1_one_on_ones - user.count_of_user_2_one_on_ones
end)}
end
end
defmodule YourCalc do
use Ash.Calculation

def load(_, _, _) do
[:count_of_user_1_one_on_ones, :count_of_user_2_one_on_ones]
end

def calculate(users, _, _) do
{:ok, Enum.map(users, fn user ->
user.count_of_user_1_one_on_ones - user.count_of_user_2_one_on_ones
end)}
end
end
Then you could say calculate :whatever_this_is_called, :integer, YourCalc But, when you can use expr/1, you should. Just showing how it might be done if you have something super custom you want to do.
dj_goku
dj_gokuOP•3y ago
Ok, thanks! That is what I thought it would be! Phew. I think I am done. I'll share once I am done with this little project. Have a good rest of your day/night Zach!
ZachDaniel
ZachDaniel•3y ago
Thanks, you as well!

Did you find this page helpful?