Как получить последние N записей с помощью activerecord?

137

С :limit в запросе я получу первые N записей. Каков самый простой способ получить последние N записей?

Теги:
activerecord

13 ответов

126
Лучший ответ

Такой активный запрос записи, как я думаю, даст вам то, что вы хотите ( "Что-то" - это имя модели):

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

edit. Как отмечено в комментариях, другой способ:

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

while !result.empty?
        puts result.pop
end
  • 0
    кажется, нет необходимости заказывать данные дважды, в настоящее время я сначала получаю счет и использую его со смещением
  • 0
    Это был другой метод, о котором я думал, но это кажется еще большей работой, так как это 2 запроса к базе данных вместо 1. Я полагаю, я предполагаю, что вам нужно перебрать массив в какой-то момент, чтобы вы могли позволить сортировке ruby это в то время. (т. е. records.reverse.each do ..)
Показать ещё 4 комментария
230

Это путь 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 более щадящий.
  • 5
    Примечание: это не очень хороший способ реализации, с точки зрения производительности - по крайней мере, не до Rails 3.1. SomeModel.last (5) выполнит оператор select без ограничения, вернув все записи SomeModel в Ruby в виде массива, после чего Ruby выберет последние (5) элементы. В плане эффективности в настоящее время вы хотите использовать ограничение - особенно если у вас есть потенциально много элементов.
Показать ещё 4 комментария
40

Новый способ сделать это в rails 3.1 является SomeModel.limit(5).order('id desc')

  • 14
    Это лучше, чем last(5) потому что возвращает область для дальнейшего объединения в цепочку.
  • 3
    Я использую SomeModel.limit(100).reverse_order в Rails 4 ( guides.rubyonrails.org/… ). Это то же самое.
Показать ещё 1 комментарий
25

Решение находится здесь:

SomeModel.last(5).reverse

Поскольку rails ленив, он, в конце концов, попадет в базу данных с SQL: "SELECT table. * FROM table ORDER BY table. id DESC LIMIT 5".

  • 0
    это загрузит все записи SomeModel
  • 0
    Лучшим подходом было бы ограничение (); это не выглядит эффективным.
Показать ещё 2 комментария
22

Для 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)
  • 0
    @ user2041318: спасибо за новый синтаксис без " "
Показать ещё 1 комментарий
5

Для 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, на самом деле. ;)
4

В моем проекте rails (rails 4.2) я использую

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

и он работает.

  • 0
    у меня тоже работал на рельсах 4.2.6. Благодарю.
4

Если вам нужно установить некоторый порядок по результатам, используйте:

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

если вам не нужен какой-либо заказ, а просто нужны записи, сохраненные в таблице, используйте:

Model.last(n) # n= any number
1

Просто попробуйте:

Model.all.order("id asc").limit(5)
  • 2
    Вы должны объяснить, почему это решение является жизнеспособным.
1

Я считаю, что этот запрос лучше/быстрее для использования метода "pluck", который мне нравится:

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

В результате получается ActiveRecord; поэтому вы можете использовать .pluck на нем следующим образом:

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

который быстро дает идентификаторы в виде массива при использовании оптимального кода SQL.

  • 0
    Challenge.limit(5).order('id desc').ids будет работать так же :)
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

Ключ - это подзапрос. Сначала нам нужно определить, какие последние сообщения мы хотим, а затем мы должны упорядочить их в порядке возрастания.

0

Если у вас есть модель по умолчанию в вашей модели, которая указывает возрастающий порядок в Rails 3, вам нужно будет использовать порядок, а не порядок, указанный Артуром Невесом выше:

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

или

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

Добавить параметр запроса в запрос

  • 1
    тогда я получу результаты в неправильном порядке

Ещё вопросы

Сообщество Overcoder
Наверх
Меню