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

LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
gonzofish
I’m currently trying to understand how to join three tables using Ecto. All the examples I’ve seen use 2, so maybe I’m just missing somet...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
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
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement