使用子查询或连接将同一模式上的两个 ecto 查询合并为一个
Combine two ecto queries on the same schema into one with subquery or join
我有一个带有虚拟字段 children
的 Post
架构,我目前正在通过 运行 在第一次获取我的 Post
后进行第二个查询来填充它。
初始查询得到 Post
:
post = Post |> Repo.get(id)
然后我 运行 进行第二个查询以获取其子项并更新虚拟 children
字段:
children_query =
from(p in Post,
where: fragment("hierarchy <@ ?", ^post.hierarchy),
order_by: p.inserted_at
)
children = Repo.all(children_query)
post = Map.merge(post, %{children: children})
层次结构字段在数据库中存储为 Ltree,在架构中具有 :string
类型。
有什么方法可以将这些查询合并为一个吗?我尝试使用 Ecto subquery/2 函数,但无法理解它。
我试过了,但无法弄清楚如何将 Post
(在本例中为 p)传递到子查询中,而不会在连接行上出现 the variable p is undefined
的错误。
def children_query(post) do
from p in Post,
where: fragment("hierarchy <@ ?", ^post.hierarchy),
order_by: v.inserted_at
end
def get_post(p_id) do
from(p in Post,
where: p.id == ^p_id,
join: c in subquery(children_query(p)),
on: p.id == c.id, # not sure how it would join on
select: %{p | children: c}
)
end
我想解决这个问题,因为当显示 Post
索引页面并且必须 运行 对列出的每个 post 进行额外的子查询时,它变得非常低效。
我想子查询不能以这种方式参数化,因为它要在主查询之前执行。可以将这两个条件移动到主查询中。
children =
from(p in Post,
join: s in subquery(from p in Post),
where: p.id == ^p_id and fragment("? <@ ?", s.hierarchy, p.hierarchy),
select: [s, p])
上面产生了一些多余的结果,Post
粘在每个 children 上,但我没有设法让它变得更好。
现在只需要拆分结果即可。
{post, children} =
case Repo.all(children) do
[[_, post] | _] = result -> {post, Enum.map(result, &hd/1)}
[] -> {Repo.get(Post, p_id), []}
end
需要后一个查询,因为当没有 children 时,连接 returns 一个空集。
我有一个带有虚拟字段 children
的 Post
架构,我目前正在通过 运行 在第一次获取我的 Post
后进行第二个查询来填充它。
初始查询得到 Post
:
post = Post |> Repo.get(id)
然后我 运行 进行第二个查询以获取其子项并更新虚拟 children
字段:
children_query =
from(p in Post,
where: fragment("hierarchy <@ ?", ^post.hierarchy),
order_by: p.inserted_at
)
children = Repo.all(children_query)
post = Map.merge(post, %{children: children})
层次结构字段在数据库中存储为 Ltree,在架构中具有 :string
类型。
有什么方法可以将这些查询合并为一个吗?我尝试使用 Ecto subquery/2 函数,但无法理解它。
我试过了,但无法弄清楚如何将 Post
(在本例中为 p)传递到子查询中,而不会在连接行上出现 the variable p is undefined
的错误。
def children_query(post) do
from p in Post,
where: fragment("hierarchy <@ ?", ^post.hierarchy),
order_by: v.inserted_at
end
def get_post(p_id) do
from(p in Post,
where: p.id == ^p_id,
join: c in subquery(children_query(p)),
on: p.id == c.id, # not sure how it would join on
select: %{p | children: c}
)
end
我想解决这个问题,因为当显示 Post
索引页面并且必须 运行 对列出的每个 post 进行额外的子查询时,它变得非常低效。
我想子查询不能以这种方式参数化,因为它要在主查询之前执行。可以将这两个条件移动到主查询中。
children =
from(p in Post,
join: s in subquery(from p in Post),
where: p.id == ^p_id and fragment("? <@ ?", s.hierarchy, p.hierarchy),
select: [s, p])
上面产生了一些多余的结果,Post
粘在每个 children 上,但我没有设法让它变得更好。
现在只需要拆分结果即可。
{post, children} =
case Repo.all(children) do
[[_, post] | _] = result -> {post, Enum.map(result, &hd/1)}
[] -> {Repo.get(Post, p_id), []}
end
需要后一个查询,因为当没有 children 时,连接 returns 一个空集。