我有一个rails API,它将JSON返回到我的React前端。我正在尝试按集合中每个项目的计算值进行排序。我有Space
模型,其中包含area
属性和count
属性。我想按total_area
对area * count
进行排序。我可以使用sort_by
执行此操作,但即使记录少于100个,此过程也非常缓慢:
@spaces = Space.all
@spaces = @spaces.sort_by(&:total_area)
其中total_area
是Space
类方法:
def total_area
self.area * self.count
end
有没有在数据库中这样做才能提高速度?我尝试使用order
方法:
@spaces.order( "count * area" => :asc)
但我得到以下postgres错误:
PG::UndefinedColumn: ERROR: column spaces.count * area does not exist
可以在数据库中执行此操作吗?任何有关我如何能够提出的建议,或者我如何更快地做到这一点都将非常感激。
答案 0 :(得分:5)
当您递送#order
哈希时:
@spaces.order("count * area" => :asc)
它假定密钥是列名,因此它将这样的SQL发送到数据库:
order by "count * area" asc
因此PG::UndefinedColumn
例外。顺便说一句,在SQL中使用双引号来引用列和表名等标识符。
如果要将表达式作为ORDER BY子句的一部分发送到数据库,那么您希望将该表达式作为字符串传递给#order
:
@spaces.order('count * area')
# If you want to be explicit about the sorting direction:
@spaces.order('count * area asc')
# If you might have other tables with those column names:
@spaces.order('spaces.count * spaces.area')
请注意,较新版本的Rails会抱怨:
当您尝试将字符串传递给#order
时,您可以通过添加Arel.sql
电话来解决这个问题:
@spaces.order(Arel.sql('count * area'))
@spaces.order(Arel.sql('count * area asc'))
@spaces.order(Arel.sql('spaces.count * spaces.area'))