Hello there
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()