在Arel NamedFunction节点中使用ORDER BY是否有一种干净的方法?

时间:2016-04-03 19:50:48

标签: ruby-on-rails rails-activerecord arel

我使用ActiveRecord 4.2 / Arel 6.0 / Postgres并输入以下内容:

  • 来自Arel::Attributes::AttributeArel::Table
  • column
  • 多个Arel::Nodes::Ordering个节点(orders

我想构建一个Arel::Nodes::NamedFunction,其聚合函数包含Attribute指定的列,并由Ordering个节点排序。

生成的SQL看起来像:

array_agg("posts"."id" ORDER BY "posts"."published_at" DESC)

我目前的解决方案是首先构建一个Arel::Nodes::SelectStatement,添加列和命令,将其转换为SQL,删除前导SELECT关键字,将其包装在Arel::Nodes::SqlLiteral和将其传递给NamedFunction节点:

select = Arel::Nodes::SelectStatement.new
select.cores.last.projections << column
select.orders = orders

sql = select.to_sql.sub(/^SELECT /, '')
literal = Arel::Nodes::SqlLiteral.new(sql)

array_agg = Arel::Nodes::NamedFunction.new('array_agg', [literal])

显然,这是一个巨大的黑客攻击。

ORDER BY保留在聚合函数之外不是一种选择,因为它会与用于聚合的GROUP BY冲突。

在没有滥用SelectStatement / SelectManager的情况下,是否有更简洁的方法来实现这一目标?

2 个答案:

答案 0 :(得分:3)

我不知道这是否适合您,但我发现这是一种干净的DESC订单。你使用了一些不同的语法,但似乎这就是你正在寻找的。

arel  = Post.arel_table
query = arel.project(Arel.select('*'))
query.order(arel[:published_at].desc).to_sql

这是我对你尝试做的最好的猜测。

答案 1 :(得分:2)

解决方案是使用 let queryString = context.req.body.query; queryString = queryString.replace(/image[\s\r\n]*?{[^}]*}/gm, ""); queryString = queryString.replace(/thumbnail[\s\r\n]*?{[^}]*}/gm, ""); return graphql(schema, queryString, null, context, context.req.body.variables) 构建“ ORDER BY”节点,并使用Arel::Nodes::InfixOperation构建逗号分隔的Arel::Nodes::StringJoin列表:

Arel::Nodes::Ordering