it-swarm.com.de

Was ist der "Rails 4-Weg", um eine Reihe von zufälligen Datensätzen zu finden?

User.find(:all, :order => "RANDOM()", :limit => 10) war die Art, wie ich es in Rails 3 gemacht habe. 

User.all(:order => "RANDOM()", :limit => 10) ist, wie ich dachte, dass Rails 4 es tun würde, aber dies gibt mir immer noch eine Warnung vor Abnahme:

DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load (e.g. `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (e.g. `Post.where(published: true).to_a`).
37
justindao

Verwenden Sie stattdessen die Methoden order und limit. Sie können die all loswerden.

Für PostgreSQL und SQLite:

User.order("RANDOM()").limit(10)

Oder für MySQL:

User.order("Rand()").limit(10)
94
Dylan Markow

Da sich die Zufallsfunktion für verschiedene Datenbanken ändern kann, würde ich empfehlen, den folgenden Code zu verwenden:

User.offset(Rand(User.count)).first

Dies ist natürlich nur nützlich, wenn Sie nur nach einem Datensatz suchen.

Wenn Sie mehr davon bekommen möchten, können Sie Folgendes tun:

User.offset(Rand(User.count) - 10).limit(10)

Der - 10 soll sicherstellen, dass Sie 10 Datensätze erhalten, falls Rand eine größere Zahl als count - 10 zurückgibt.

Denken Sie daran, dass Sie immer 10 aufeinanderfolgende Datensätze erhalten.

31
maurimiranda

Ich denke, die beste Lösung ist die zufällige Reihenfolge in der Datenbank ..__ Wenn Sie jedoch bestimmte Zufallsfunktionen aus der Datenbank vermeiden möchten, können Sie pluck und shuffle verwenden.

Für einen Datensatz:

User.find(User.pluck(:id).shuffle.first)

Für mehr als einen Datensatz:

User.where(id: User.pluck(:id).sample(10))
19
Prodis

Ich würde vorschlagen, dass dies ein Gültigkeitsbereich ist, da Sie es dann verketten können:

class User < ActiveRecord::Base
  scope :random, -> { order(Arel::Nodes::NamedFunction.new('RANDOM', [])) }
end 

User.random.limit(10)
User.active.random.limit(10)
8
Kyle Decot

Obwohl dies nicht die schnellste Lösung ist, mag ich die Kürze von:

User.ids.sample(10)

Die Methode .ids Liefert ein Array von Benutzer-IDs, und .sample(10) wählt 10 zufällige Werte aus diesem Array aus.

7
evaneykelen

Für MYSQL hat das für mich funktioniert:

User.order("Rand()").limit(10)
1
beesasoh

Empfehlen Sie diesen Edelstein dringend für zufällige Datensätze, der speziell für Tabellen mit vielen Datenzeilen entwickelt wurde:

https://github.com/haopingfan/quick_random_records

Alle anderen Antworten funktionieren mit großer Datenbank schlecht, mit Ausnahme dieses Edelsteins: 

  1. quick_random_records kostet nur 4.6ms total.

 enter image description here

  1. die akzeptierte Antwort User.order('Rand()').limit(10) kostet 733.0ms.

 enter image description here

  1. der offset-Ansatz kostet 245.4ms insgesamt.

 enter image description here

  1. die User.all.sample(10) Annäherungskosten 573.4ms.

 enter image description here

Hinweis: Mein Tisch hat nur 120.000 Benutzer. Je mehr Datensätze Sie haben, desto größer ist der Leistungsunterschied.


AKTUALISIEREN: 

Führen Sie eine Tabelle mit 550.000 Zeilen aus

  1. Model.where(id: Model.pluck(:id).sample(10)) kosten 1384.0ms

 enter image description here

  1. gem: quick_random_records kostet nur 6.4ms vollständig

 enter image description here

1
Derek Fan

Sie könnten .sample für die Datensätze aufrufen, wie: User.all.sample(10)

0
s2t2