job
模式看起来像这样:
schema "jobs" do
# more fields and associations
field :fulfilled, :boolean, virtual: true
end
我有需要正常工作的SQL:
SELECT jobs.*, (SELECT COUNT(1) = 0
AS fulfilled
FROM slots
JOIN slot_groups on slots.slot_group_id = slot_groups.id
JOIN scopes ON slot_groups.scope_id = scopes.id
WHERE scopes.job_id = 1 AND slots.supplier_crew_member_id IS NULL)
FROM jobs
WHERE jobs.id = 1;
但是将其转换为Ecto.Query
语法非常困难。
这与我的工作差不多:
def get_job(id) do
Job
|> where([j], j.id == ^id)
|> select_merge([j], ^fulfilled(id))
|> Repo.one()
end
defp fulfilled(job_id) do
Api.Slots.Slot
|> join(:inner, [slot], slot_group in assoc(slot, :slot_group))
|> join(:inner, [slot, slot_group], scope in assoc(slot_group, :scope))
|> where([slot, _slot_group, scope], scope.job_id == ^job_id and is_nil(slot.supplier_crew_member_id))
|> select([_slot, _slot_group, _scope], %{fulfilled: fragment("count(1) = 0 AS fulfilled")})
end
但出现以下错误:
** (ArgumentError) expected a list of fields in `select/2` inside `select`, got: `#Ecto.Query<from s0 in Api.Slots.Slot, join: s1 in assoc(s0, :slot_group), join: s2 in assoc(s1, :scope), where: s2.job_id == ^2 and is_nil(s0.supplier_crew_member_id), select: %{fulfilled: fragment("count(1) = 0 AS fulfilled")}>`
(ecto) lib/ecto/query/builder/select.ex:160: Ecto.Query.Builder.Select.fields!/2
(ecto) lib/ecto/query/builder/select.ex:177: Ecto.Query.Builder.Select.select!/5
(api) lib/api/jobs/jobs.ex:28: Api.Jobs.get_job/1
任何帮助将不胜感激!
答案 0 :(得分:1)
实际上我最终弄清楚了我需要什么。原来是Subqueries are currently only supported in the from and join fields
。
我转为使用关键字语法,并创建了一个子查询,该子查询针对外部查询加入,如下所示:
job_slots_fulfilled_query =
from(
from jobs in Api.Jobs.Job,
left_join: scopes in assoc(jobs, :scopes),
left_join: slot_groups in assoc(scopes, :slot_groups),
left_join: slots in assoc(slot_groups, :slots),
where: jobs.organization_id == ^org_id,
group_by: jobs.id,
select: %{
id: jobs.id,
fulfilled: fragment("every(?)", not is_nil(slots.supplier_crew_member_id))
}
)
Repo.all(
from(
j in Job,
left_join: s in subquery(job_slots_fulfilled_query),
on: j.id == s.id,
where: j.organization_id == ^org_id,
select_merge: %{fulfilled: s.fulfilled},
preload: [:organization, :owner, :job_type, :scopes]
)
)