Role CRUD LiveViews closes #325 #326
1 changed files with 15 additions and 20 deletions
|
|
@ -126,33 +126,28 @@ defmodule MvWeb.RoleLive.Index do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Loads all user counts for roles in a single query to avoid N+1 queries
|
# Loads all user counts for roles using DB-side aggregation for better performance
|
||||||
# TODO: Optimize to use DB-side aggregation instead of loading all users
|
|
||||||
@spec load_user_counts([Mv.Authorization.Role.t()], map() | nil) :: %{
|
@spec load_user_counts([Mv.Authorization.Role.t()], map() | nil) :: %{
|
||||||
Ecto.UUID.t() => non_neg_integer()
|
Ecto.UUID.t() => non_neg_integer()
|
||||||
}
|
}
|
||||||
defp load_user_counts(roles, actor) do
|
defp load_user_counts(roles, _actor) do
|
||||||
role_ids = Enum.map(roles, & &1.id)
|
role_ids = Enum.map(roles, & &1.id)
|
||||||
|
|
||||||
# Load all users with role_id in a single query
|
# Use Ecto directly for efficient GROUP BY COUNT query
|
||||||
opts = opts_with_actor([], actor, Mv.Accounts)
|
# This is much more performant than loading all users and counting in Elixir
|
||||||
|
# Note: We bypass Ash here for performance, but this is a simple read-only query
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
users =
|
query =
|
||||||
case Ash.read(
|
from u in Accounts.User,
|
||||||
Accounts.User
|
where: u.role_id in ^role_ids,
|
||||||
|> Ash.Query.filter(role_id in ^role_ids)
|
group_by: u.role_id,
|
||||||
|> Ash.Query.select([:role_id]),
|
select: {u.role_id, count(u.id)}
|
||||||
opts
|
|
||||||
) do
|
|
||||||
{:ok, users_list} -> users_list
|
|
||||||
{:error, _} -> []
|
|
||||||
end
|
|
||||||
|
|
||||||
# Group by role_id and count
|
results = Mv.Repo.all(query)
|
||||||
users
|
|
||||||
|> Enum.group_by(& &1.role_id)
|
results
|
||||||
|> Enum.map(fn {role_id, users_list} -> {role_id, length(users_list)} end)
|
|> Enum.into(%{}, fn {role_id, count} -> {role_id, count} end)
|
||||||
|> Map.new()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gets user count from preloaded assigns map
|
# Gets user count from preloaded assigns map
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue