Activerecord ile son N kayıtları nasıl alabilirim?


Yanıtlar:


143

Bunun gibi aktif bir kayıt sorgusu size ne istediğini alırsınız ('Bir şey' model adıdır):

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

edit : Yorumlarda belirtildiği gibi, başka bir yol:

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

while !result.empty?
        puts result.pop
end

Veriyi iki kez sipariş etmek gereksiz görünüyor, şu anda önce sayımı alıyorum ve ofset ile kullanıyorum
JtR

Bu düşündüğüm diğer yöntemdi, ama veritabanı yerine 2 sorgu 2 yerine bu daha da fazla iş gibi görünüyor Sanırım ben bir noktada dizi üzerinde yinelemek gerektiğini varsayıyorum, böylece yakut sıralama izin verebilir o zaman. (örn. kayıtlar.
ters

Alternatif olarak, diziyi tersine çevirip diziyi tersine çevirmek yerine yinelemek için Array.pop'u kullanamazsınız
Dan McNevin

1
Rails 3 için, bunun yerine Bong'un cevabına bakın. Bu yol hala çalışıyor, ancak artık tercih edilen yol değil.
Kyle Heironimus

3
#Find (: all) çağrısında kullanımdan kaldırıldı. Bunun yerine #all doğrudan arayın.
Snowcrash

262

Bu Rails 3 yoludur

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

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

4
Postgres ile bunu deneyin! İlk önce kesinlikle sorun yaşadım. SQL'de, siz belirtmedikçe sipariş garanti edilmez, ancak MySQL daha bağışlayıcıdır.
Ghoti

5
Not: Bu, performans açısından akıllıca uygulanmanın iyi bir yolu değildir - en azından Rails 3.1'e kadar değil. SomeModel.last (5), select deyimini sınırsız olarak yürütür ve SomeModel'in tüm kayıtlarını dizi olarak Ruby'ye döndürür, ardından Ruby son (5) öğeyi seçer. Verimlilik açısından, şu anda sınır kullanmak istiyorsunuz - özellikle potansiyel olarak çok fazla elemanınız varsa.
DRobinson

14
Tam olarak ne yapması gerekiyor:SELECT "items".* FROM "items" ORDER BY id DESC LIMIT 50
firedev

7
Rails 4'te .last () tarafından oluşturulan sorgu, Nick'in belirttiği gibi de en uygunudur
Jimmie Tyrrell

1
Bu, SomeModel.last(5).class== nedeniyle Rails 4+ için yanlıştır Array. Doğru yaklaşım SomeModel.limit(5).order('id desc')Arthur Neves'e göre, sonuç:SELECT \"somemodels\".* FROM \"somemodels\" ORDER BY id desc LIMIT 5
Amin Ariana

50

raylar 3.1 bunu yapmanın yeni yolu SomeModel.limit(5).order('id desc')


14
Bu, daha fazla last(5)zincirleme için bir kapsam döndürdüğü için daha iyidir .
lulalala

3
Kullandığım SomeModel.limit(100).reverse_orderRaylar 4 (üzerinde guides.rubyonrails.org/... de aynı durum geçerlidir).
Ivan Black

@Lulalala bahsettiği "ileri zincirleme için kapsam" örneği: Tek sütun gerekiyorsa, SomeModel.limit(5).order('id desc').pluck(:col)yapacağız SELECT SomeModel.col FROM SomeModel ORDER BY id desc LIMIT 5çok daha verimli tüm sütunları kapma ve tüm ama bir sütun ile atmadan daha hangi SomeModel.last(5).map(&:col) bağlantıda bulunduğu SELECT *yerine SELECT col(aradığınız olamaz koparmak sonra son; tembel-değerlendirme zinciri son ile biter).
Kanat Bolazar

33

Raylar 5 için (ve muhtemelen Raylar 4 için)

Kötü:

Something.last(5)

Çünkü:

Something.last(5).class
=> Array

yani:

Something.last(50000).count

muhtemelen hafızanızı havaya uçuracak veya sonsuza kadar sürecektir.

Iyi bir yaklaşım:

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

Çünkü:

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"

İkincisi değerlendirilmemiş bir kapsamdır. Zincir oluşturabilir veya bir diziye dönüştürebilirsiniz .to_a. Yani:

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

... bir saniye sürüyor.


1
Ve hatta Rails 3 bile. ;)
Joshua Pinter

32

İçin Raylar 4 ve sürüm yukarıdaki:

İlk en eski girişi istiyorsanız böyle bir şey deneyebilirsiniz

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

En son girişleri istiyorsanız böyle bir şey deneyebilirsiniz ..

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

1
Bu, Rails 4 için kabul edilenden daha güncel bir cevap gibi görünüyor. En son sözdiziminin şöyle görünmesi gerektiğini düşünüyorum:YourModel.all.order(id: :desc).limit(5)
jmarceli

@ user2041318: Bu yeni sözdizimi için teşekkürler" "
Gagan Gami

2
Order () tüm kayıtları döndürür. Zincire gerek yok YourModel.all.order()çünkü aynıYourModel.order()
Francisco Quintero

26

Çözüm burada:

SomeModel.last(5).reverse

Raylar tembel olduğu için, sonunda veritabanına SQL gibi vuracaktır: "SELECT table. * table SİPARİŞ TARAFINDAN table. idDESC LIMIT 5".


bu tüm kayıtları yüklerSomeModel
John Hinnegan

Daha iyi bir yaklaşım limit (); bu verimli görünmüyor.
Anurag

3
@Developer kesinlikle doğru. Yürütülen SQL şöyleydi: SELECT table .* FROM table` ORDER BY table. idAZALAN SINIR 5` o mu değil bir bütün seçmek gerçekleştirmek
ddavison

4

Sonuçlar için bir sipariş vermeniz gerekiyorsa şunu kullanın:

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

Herhangi bir siparişe ihtiyacınız yoksa ve sadece tabloya kaydedilmiş kayıtlara ihtiyacınız varsa kullanın:

Model.last(n) # n= any number

4

Ray projemde (rails 4.2)şunu kullanıyorum

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

ve çalışıyor.



2

Sadece dene:

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

2
Bu çözümün neden geçerli olduğunu açıklamalısınız.
Phiter

1

Bu sorguyu daha iyi / daha hızlı seviyorum "pluck" yöntemi kullanmak için bulmak:

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

Bu çıktı olarak bir ActiveRecord verir; böylece .pluck komutunu şu şekilde kullanabilirsiniz:

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

optimal SQL kodunu kullanırken kimlikleri hızlı bir şekilde dizi olarak verir.


Challenge.limit(5).order('id desc').idsde işe yarayacak :)
Koen.

0

Modelinizde Rails 3'te artan bir sipariş belirten varsayılan bir kapsamınız varsa, yukarıdaki Arthur Neves tarafından belirtildiği gibi sipariş yerine yeniden sipariş vermeniz gerekir:

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

veya

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

0

Diyelim ki N = 5 ve modeliniz şu Messageşekilde bir şey yapabilirsiniz:

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

Sql bak:

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

Anahtar alt seçenektir. Öncelikle istediğimiz son mesajların ne olduğunu tanımlamamız ve sonra bunları artan sırada sipariş etmemiz gerekiyor.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.