How to add Ecto.Query.API count() to Repo.preload?

Hi,

I’m trying to preload some data to my user and I would like to add number of user notifications to the preload, not the notifications itself, just the count.

query # fetches the user
|> Repo.one()
|> Repo.preload([:profile, notifications: from(n in Notification, group_by: n.id, select: count(n.id))])

With this query I get one entry inside the list for each notification.

#MyApp.Accounts.User<
  __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  id: 6,
  ...
  notifications: [1, 1, 1, 1]

How do I count the notifications with the db so I would get:

#MyApp.Accounts.User<
  __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  id: 6,
  ...
  notifications: [4]

Thanks

I’d suggest using a virtual fields and select the count instead of kinda abusing preloads (which are a assoc/embed thing) for that.

Do you have some example maybe? I’ve used virtual fields with forms in the past but I don’t really understand how am I supposed to use them here.

And just to clarify, I used preload here to avoid making another query to the db just for counting notifications.

You are making another query here. Preloads use separate queries unless you bind them using joined data in queries.

defmodule Example do
  use Ecto.Schema
  import Ecto.Query
  
  schema "examples" do
    field :computed, :integer, virtual: true
  end
  
  def with_computed do
    from e in Example, select_merge: %{computed: 10}
  end
end
2 Likes