ruby每个循环按顺序在sql命令查询结果上

时间:2018-02-10 20:21:27

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

我的控制器中有一个完美运行的查询:

  

@klasses_mon = Klass.order(:start).where(day:' MON')。find_each

我的结果是(在我看来<%= @klasses_mon.inspect %>显示):

#<Enumerator: #<ActiveRecord::Relation 
[#<Klass id: 9, name: "Cycling", teacher: "Tomek", day: "MON", start: 510, duration: 45>,
#<Klass id: 8, name: "LBT", teacher: "Monia", day: "MON", start: 600, duration: 60>, 
#<Klass id: 11, name: "HIIT", teacher: "Aga", day: "MON", start: 930, duration: 45>]>
:find_each({:start=>nil, :finish=>nil, :batch_size=>1000, :error_on_ignore=>nil})>

但我试图在每个循环中显示它。由于某种原因,它不再被订购。看起来每个循环都不会保留查询结果的顺序:

<% @klasses_mon.each do |k| %>
    <p><%= k.teacher %>,
    <%= k.name %>
    START: <%= k.start/60 %>:<%= k.start%60 %>
<% end %>

结果:

  

Monia,LBT START:10:0

     

Tomek,Cycling START:8:30

     

Aga,HIIT START:15:30

我该怎么做?

2 个答案:

答案 0 :(得分:2)

来自fine manual

  

find_each (start:nil,finish:nil,batch_size:1000,error_on_ignore:nil)
  [...]
  注意:无法设置订单。在主键(“id ASC”)上自动设置为升序,以使批量订购工作。这也意味着此方法仅在主键可订购时有效(例如整数或字符串)。

因此明确记录find_each以忽略您尝试使用的任何排序。

find_each不使用LIMIT和OFFSET将批处理窗口移动到结果集中,因为随着OFFSET的增加,它往往非常昂贵,而是按主键排序并包含{{1}用于设置批处理开始的WHERE子句中的condition和用于设置批处理大小的LIMIT子句。通过PK排序和查询PK通常都是廉价的,因为LIMIT条款。

id > last_one是这项工作的错误工具,find_each用于批处理工作,但您只是显示一个简短的记录列表,所以您想要一个简单的工具:

find_each

答案 1 :(得分:1)

方法#find_each忽略任何作用域order并强制按主键排序(通常为id)。这在documentation中说明,因为#find_each需要确保它在迭代期间不会重复任何记录。

如果您尝试:

,您可以在控制台中看到此信息
> @klasses_mon = Klass.order(:start).where(day: 'MON').find_each
> @klasses_mon.map(&:start) # force the relation to execute and return rows.
Scoped order is ignored, it's forced to be batch order.
Klass Load (0.ms) SELECT "klasses".* FROM "klasses" WHERE "klasses"."day" = 'MON' ORDER BY "klasses"."id"
=> [600, 510, 930]

如果您不希望经历数千行,则可以删除find_each

@klasses_mon = Klass.where(day: "MON").order(:start)