Yama

Yama

Sorry for asking something that has been mentioned a few times here but would like some help to get a better understanding. What I’m trying to do is be able to return a list of tags with the number of posts that has a tag associated with it.

    subquery = from(pt in PostTag, select: %{postCount: count(pt.tag_id)}, group_by: pt.tag_id)

    query =
      from(t in Tag,
        join: pt in subquery(subquery),
        on: t.id == pt.tag_id,
        where: ilike(t.name, ^search),
        select: %{id: t.id, name: t.name, count: pt.postCount},
        group_by: t.id
      )

We want to be able to return something like %{id: "1", count: 4} where the count is the number of posts associated with that tag. I currently have 3 tables, Post, Tag, and PostTags which connects the other two as many to many association.

I was hoping to get a better understanding of why I’m getting this error t0.id" must appear in the GROUP BY clause or be used in an aggregate function.

Thanks for the help and clarity in regards to this problem and pointing in the right direction in solving it.

Showing Posts 1 to 5

Yama

Yama OP

I believe I may have found a solution. Would love some input if there is a better approach or maybe some flaws so what seems to be working. Thanks again

  def get_tags(search) do
    subquery =
      from(pt in PostTag,
        select: %{tag_id: pt.tag_id, postCount: count(pt.tag_id)},
        group_by: pt.tag_id
      )

    query =
      from(t in Tag,
        join: pt in subquery(subquery),
        on: t.id == pt.tag_id,
        where: ilike(t.name, ^search),
        select: %{id: t.id, name: t.name, count: pt.postCount}
      )

    # from(t in Tag, join: p in assoc(:posts), select: t.name)
    Repo.all(query)
  end
OvermindDL1

OvermindDL1

Nothing to do with ecto, that error was coming from your SQL server.

And I’d guess it was because the subquery made no export of tag_id, the select only returned postCount without any correlation of matching.

Personally I would not have had a subquery, rather just a (left_)join and group based on the id/name and aggregate (count) the post’s table.

dalerka

dalerka

I’m also interested and couldn’t find an example for such common use case in Ecto docs.
Is this efficient way to do it?

Do you mind sharing some code example, eg. a best practice of doing this with Ecto?

Also, do you recommend “caching” the count of related Posts on Tag schema, eg. Tag.posts_count and how to do it efficiently (maybe with Ecto.Multi upon PostTag insert?) in many-to-many relations?

Basically, I’d like to list all tags (could be hundreds) and have the count of relevant posts attached to each tag returned from the DB, and have the counts update (in a liveview) as posts being created with some tags. What’s the wiser way to implement this?

dalerka

dalerka

So, as recommended here… we can add a virtual posts_count field to Tag schema.
Also we need to convert the maps returned by the query into structs as follows:

def list_tags_with_posts_count do
  query =
    from(t in Tag,
      left_join: p in assoc(t, :posts),
      group_by: t.id,
      select: %{id: t.id, name: t.name, posts_count: count(p.id)},
      order_by: [asc: :name]
    )

  query
  |> Repo.all()
  |> Enum.map(fn tag -> struct(Tag, tag) end)
end
Nicodemus

Nicodemus

I found this thread while researching options for adding aggregated results to a list, and would like to propose a different way to do it that doesn’t require any extra mapping or struct building for anyone else looking. Apologies for necro-posting.

First, add a virtual field to the Tag schema:

field :posts_count, :integer, virtual: true

Then simply merge the aggregate result into the existing list of returned structs, which if there is no select in the query it defaults to the full schema (equivalent to select: t.)

def list_tags_with_posts_count do
  Repo.all(
    from t in Tag,
      left_join: p in assoc(t, :posts),
      group_by: t.id,
      order_by: [asc: :name],
      select_merge: %{posts_count: count(p.id)}
  )
end
— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
csmr
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley: Mutonex gamedesign was finish...
New
Stef-Verniers
Hello I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
kip
In 2021 I started a new library called Tempo with the objective of modelling time as a set of intervals - not as instants. In 2022 I gave...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews