在 Ecto 中,预加载聚合查询

In Ecto, preloading an aggregate query

假设我有 table 个 postscommentsvotes

votes table 有一个 direction 列,它是 1、0 或 -1。

我想查询所有的post条,还有count条评论,sumvotes.direction 每个 post.

这是否可以作为 Ecto 中的子查询来实现,最好是在 Post 模型上使用可组合查询?

目前我拥有的是:

def count_comments(query) do
  from p in query,
    left_join: c in assoc(p, :comments),
    select: {p, count(c.id)},
    group_by: p.id
end

def get_score(query) do
  from l in query,
    left_join: v in assoc(p, :votes),
    select: {p, sum(v.direction)},
    group_by: p.id
end

但我无法同时编写这两个查询,因为出现此错误:

(Ecto.Query.CompileError) only one select expression is allowed in query

不清楚您的代码在什么地方失败了,但很可能通过以下方式完成:

from p in Post,
  left_join: c in assoc(p, :comments),
  left_join: v in assoc(p, :votes),
  group_by: p.id,
  select: {p, count(c.id), sum(v.direction)}

Query compisition 仅允许用于“未终止”查询,也就是说,对于没有 select 子句的查询(未经测试,您的结构可能略有不同):

with_comments =
  from p in Post,
  left_join: c in assoc(p, :comments),
  group_by: p.id

with_score_and_comments = 
  from [p, c] in with_comments,
  left_join: v in assoc(p, :votes),
  group_by: p.id

result =
  from [p, c, v] in with_score_and_comments,
  select: {p, count(c.id), sum(v.direction)}