JasterV

JasterV

How to make a query in Ecto that checks if a Schema is related to another schema in a One to Many relationship

Hello there :slight_smile:

I have a schema A that has a one-to-many relationship with a schema B.

I want to make a query that lists all rows in schema A + have an extra boolean like “has_any_b_associated?”

Right now I’m doing it using a virtual field and a subquery but I wonder if there is any other simpler way to do it?

Here is the code I have right now:

Module “A”:

defmodule MyApp.Schema.A do
  @moduledoc false

  use Ecto.Schema

  import Ecto.Changeset
  import Ecto.Query

  alias MyApp.Schema.B

  @type t :: %__MODULE__{}

  @fields [
    :id
  ]

  @required_fields [
    :id
  ]

  @primary_key {:id, :binary_id, autogenerate: false}
  schema "a" do
    has_many :b, B

    field :has_any_b_associated?, :boolean, virtual: true

    timestamps()
  end

  @spec changeset(t(), map()) :: Ecto.Changeset.t()
  def changeset(%__MODULE__{} = data \\ %__MODULE__{}, attrs) do
    data
    |> cast(attrs, @fields)
    |> validate_required(@required_fields)
  end

  @spec with_has_any_b_associated?(__MODULE__ | Ecto.Query.t()) :: Ecto.Query.t()
  def with_has_any_b_associated?(query \\ __MODULE__) do
    from r in query,
      as: :schema_a,
      select: %{
        r
        | has_any_b_associated?:
            exists(
              from(
                b in B,
                where: parent_as(:schema_a).id == b.a_id,
                select: 1
              )
            )
      }
  end
end

How I build the query:

Schema.A |> Schema.A.with_has_any_b_associated?() |> Repo.all()

Most Liked

sodapopcan

sodapopcan

Another way:

from r in query,
  left_join: b in assoc(r, :b),
  select_merge: %{
    has_any_b_associated?: count(b.id) > 0
  },
  group_by: r.id

I can’t speak to which one is more performant.

nilsonjrx

nilsonjrx

that’s what I’d do. the virtual field + exists subsquery combo is a good choice (actually, exists is my top1 tool when I want to check conditions under relations without replicating rows with joins).

Where Next?

Popular in Questions Top

New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement