如何使用activerecord获得最后N条记录?


163

通过:limit查询,我将获得前N条记录。获取最后N条记录的最简单方法是什么?

Answers:


143

我认为这样的活动记录查询可以为您提供所需的信息(“名称”是模型名称):

Something.find(:all, :order => "id desc", :limit => 5).reverse

编辑:如评论中所述,另一种方式:

result = Something.find(:all, :order => "id desc", :limit => 5)

while !result.empty?
        puts result.pop
end

似乎没有必要对数据进行两次排序,我目前正在首先获取计数并与偏移量
一起

那是我在想的另一种方法,但是似乎还需要更多工作,因为这是针对数据库的2个查询,而不是1个。我想我假设您需要在某个时刻迭代数组,以便让ruby排序在那个时候。(即
records.reverse.each

或者,您不能反转数组,而不能使用Array.pop遍历数组而不是反转数组。.ruby
doc.org/

1
对于Rails 3,请参阅Bongs的回复。这种方式仍然有效,但不再是首选方式。
Kyle Heironimus'4

3
不建议调用#find(:all)。而是直接致电#all。
Snowcrash 2013年

262

这是Rails 3的方式

SomeModel.last(5) # last 5 records in ascending order

SomeModel.last(5).reverse # last 5 records in descending order

4
与Postgres一起尝试!我当然先遇到麻烦了。在SQL中,除非您指定顺序,否则不能保证顺序,但是MySQL更宽容。
Ghoti

5
注意:从性能角度来看,这不是实现它的好方法-至少不是Rails 3.1所能做到的。SomeModel.last(5)将无限制地执行select语句,将SomeModel的所有记录作为数组返回给Ruby,之后Ruby将挑选出最后(5)个元素。在效率方面,当前,您想使用限制-尤其是在您可能有很多元素的情况下。
DRobinson

14
它确实做了它应该做的:SELECT "items".* FROM "items" ORDER BY id DESC LIMIT 50
firedev

7
在Rails 4中,如Nick提到的,由.last()生成的查询也是最佳的
Jimmie Tyrrell

1
对于Rails 4+,这是不正确的,因为SomeModel.last(5).class== Array。正确的方法是SomeModel.limit(5).order('id desc')根据亚瑟·内维斯(Arthur Neves)的说法,这将导致SELECT \"somemodels\".* FROM \"somemodels\" ORDER BY id desc LIMIT 5
阿敏·阿里亚纳

50

在Rails 3.1中做到这一点的新方法是 SomeModel.limit(5).order('id desc')


14
这比last(5)因为它返回进一步链接的范围更好。
lulalala

3
SomeModel.limit(100).reverse_order在Rails 4(guides.rubyonrails.org/…)上使用相同。
伊万·布莱克

由@lulalala提到“范围进一步链接”的例子:如果你只需要一列,SomeModel.limit(5).order('id desc').pluck(:col)会做SELECT SomeModel.col FROM SomeModel ORDER BY id desc LIMIT 5比抓住所有列,并丢弃所有,但一列以更有效SomeModel.last(5).map(&:col) ,其确实SELECT *而不是SELECT col(你不能调用后摘去last;惰性评估链以last结尾)。
Kanat Bolazar 2015年

33

对于Rails 5(可能还有Rails 4)

坏:

Something.last(5)

因为:

Something.last(5).class
=> Array

所以:

Something.last(50000).count

可能会炸毁您的记忆或永久占用。

好的方法:

Something.limit(5).order('id desc')

因为:

Something.limit(5).order('id desc').class
=> Image::ActiveRecord_Relation

Something.limit(5).order('id desc').to_sql
=> "SELECT  \"somethings\".* FROM \"somethings\" ORDER BY id desc LIMIT 5"

后者是未评估的范围。您可以将其链接,也可以通过将其转换为数组.to_a。所以:

Something.limit(50000).order('id desc').count

...需要一秒钟。


1
甚至是Rails 3。;)
约书亚·品特

32

对于Rails 4及更高版本:

您可以尝试这样的操作如果您想要最早的条目

YourModel.order(id: :asc).limit(5).each do |d|

如果您想要最新的条目,可以尝试这样的操作。

YourModel.order(id: :desc).limit(5).each do |d|

1
对于Rails 4,这似乎是最新的答案,而不是公认的答案。我认为最新的语法应如下所示:YourModel.all.order(id: :desc).limit(5)
jmarceli 2014年

@ user2041318:感谢您提供的这种新语法-Gagan " "
Gami

2
Order()返回所有记录。不需要链接,YourModel.all.order()因为与YourModel.order()
Francisco Quintero

26

解决方案在这里:

SomeModel.last(5).reverse

由于轨是懒惰的,它最终将击中像SQL数据库: “SELECT table* FROM。table ORDER BY tableidDESC LIMIT 5”。


这将载入SomeModel
John Hinnegan 2013年

更好的方法是limit(); 这看起来效率不高。
阿努拉格

3
@Developer是绝对正确的。执行的SQL是:SELECT table .* FROM table` ORDER BY tableidDESC LIMIT 5`它并没有进行全选
ddavison

4

如果您需要对结果进行一些排序,请使用:

Model.order('name desc').limit(n) # n= number

如果不需要任何排序,只需要将记录保存在表中,则使用:

Model.last(n) # n= any number

4

在我的rails (rails 4.2)项目中,我使用

Model.last(10) # get the last 10 record order by id

而且有效。



2

试一试:

Model.order("field_for_sort desc").limit(5)

2
您应该解释为什么该解决方案可行。
Phiter

1

我发现此查询对于使用我喜欢的“ pluck”方法更好/更快。

Challenge.limit(5).order('id desc')

这给出一个ActiveRecord作为输出;因此您可以像这样使用.pluck:

Challenge.limit(5).order('id desc').pluck(:id)

在使用最佳SQL代码时,可以快速将id作为数组给出。


Challenge.limit(5).order('id desc').ids也会一样好:)
Koen。

0

如果您的模型中有一个默认范围,它在Rails 3中指定了升序,则需要使用重新排序,而不是上面的Arthur Neves指定的顺序:

Something.limit(5).reorder('id desc')

要么

Something.reorder('id desc').limit(5)

0

假设N = 5,而您的模型是Message,则可以执行以下操作:

Message.order(id: :asc).from(Message.all.order(id: :desc).limit(5), :messages)

看一下sql:

SELECT "messages".* FROM (
  SELECT  "messages".* FROM "messages"  ORDER BY "messages"."created_at" DESC LIMIT 5
) messages  ORDER BY "messages"."created_at" ASC

关键是子选择。首先,我们需要定义我们想要的最后一条消息,然后我们必须按升序对其进行排序。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.