给定有效记录scope
,如何在给定记录后返回N条记录?
例如,考虑我们有一个按人口排序的城市地区列表:
有效记录范围:
Area.ordered_by_population
返回的行:
ID | Area
------------
9 | Tokyo
2 | Jakarta
7 | Seoul
1 | Delhi
8 | Shanghai
4 | Manila
3 | Karachi
5 | New York City
6 | São Paulo
现在我需要在ID 8(上海)之后返回3条下一条记录。结果将是:
4 | Manila
3 | Karachi
5 | New York City
rails调用将如下所示:
Area.ordered_by_population.records_after_id(id: 8, count: 3)
那么,我该如何编写这个records_after_id
方法?
性能要求:该方法应该处理具有100K记录的数据库表并且速度相对较快(我在现代笔记本电脑上的目标是1ms)。
Beerlington注意到这个问题的重要细微差别。不幸的是,我无法使用分页解决方案。我需要在给定记录后返回行。它必须相对于记录。
答案 0 :(得分:2)
我可能误解了这个问题,但听起来你想要的是分页,而你实际上并不关心这个ID。我过去使用Kaminari gem成功了。只需更改查询中的limit
和offset
,您就可以在没有gem的情况下执行此操作,但gem使得管理更加用户友好。
与Kaminari:
Area.ordered_by_population.page(1).per(8)
Area.ordered_by_population.page(2).per(8)
Area.ordered_by_population.page(3).per(8)
没有Kaminari:
Area.ordered_by_population.limit(10).offset(0)
Area.ordered_by_population.limit(10).offset(10)
Area.ordered_by_population.limit(10).offset(20)
答案 1 :(得分:2)
records_after_id
方法可以定义如下
module Pager
def records_after_id(id:, count:)
relation = self.dup
# perform the query and find the index of the id
offset = relation.pluck(:id).find_index(id)
# OFFSET LIMIT query starting +1 after the found id
relation.offset(offset + 1).limit(count)
end
end
然后你可以按如下方式调用它
Area.ordered_by_population.extending(Pager).records_after_id(id: 8, count: 3)
当返回Relation
时,它可以被扩展,比如接下来3条记录的总和
Area.ordered_by_population
.extending(Pager)
.records_after_id(id: 8, count: 3)
.sum(:population)
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-extending
的更多信息