Entonces, he encontrado varios ejemplos para encontrar un registro aleatorio en Rails 2; el método preferido parece ser:
Thing.find :first, :offset => rand(Thing.count)
Al ser un novato, no estoy seguro de cómo podría construirse esto utilizando la nueva sintaxis de búsqueda en Rails 3.
Entonces, ¿cuál es el "Rails 3 Way" para encontrar un registro aleatorio?
Respuestas:
o
En realidad, en Rails 3 todos los ejemplos funcionarán. Pero usar el orden
RANDOM
es bastante lento para tablas grandes pero más estilo sqlUPD Puede usar el siguiente truco en una columna indexada (sintaxis PostgreSQL):
fuente
RAND()
oRANDOM()
. GraciasEstoy trabajando en un proyecto ( Rails 3.0.15, ruby 1.9.3-p125-perf ) donde el db está en localhost y la tabla de usuarios tiene un poco más de 100K registros .
Utilizando
es bastante lento
se convierte
y toma de 8 a 12 segundos para responder !!
Registro de rieles:
de explicar mysql
Puede ver que no se utiliza ningún índice ( possible_keys = NULL ), se crea una tabla temporal y se requiere un pase adicional para obtener el valor deseado ( extra = Uso temporal; Uso de clasificación de archivos ).
Por otro lado, al dividir la consulta en dos partes y usar Ruby, tenemos una mejora razonable en el tiempo de respuesta.
(; nulo para uso de consola)
Registro de rieles:
y la explicación de mysql prueba por qué:
¡ahora solo podemos usar índices y la clave principal y hacer el trabajo unas 500 veces más rápido!
ACTUALIZAR:
Como lo señala icantbecool en los comentarios, la solución anterior tiene un defecto si hay registros eliminados en la tabla.
Una solución alternativa en eso puede ser
que se traduce en dos consultas
y se ejecuta en unos 500 ms.
fuente
RAND(id)
será NO le dará un orden aleatorio diferente cada consulta. ÚseloRAND()
si desea un orden diferente en cada consulta.Si usa Postgres
Si usa MySQL
En ambos casos, está seleccionando 5 registros al azar de la tabla Usuarios. Aquí se muestra la consulta SQL real en la consola.
fuente
Hice una gema de rieles 3 para hacer esto que funciona mejor en tablas grandes y le permite encadenar relaciones y ámbitos:
https://github.com/spilliton/randumb
(editar): el comportamiento predeterminado de mi gema básicamente utiliza el mismo enfoque que el anterior ahora, pero tiene la opción de usar el método antiguo si lo desea :)
fuente
Muchas de las respuestas publicadas en realidad no funcionarán bien en tablas bastante grandes (1+ millones de filas). La ordenación aleatoria tarda unos segundos y hacer un recuento en la mesa también lleva bastante tiempo.
Una solución que me funciona bien en esta situación es usar
RANDOM()
una condición where:En una tabla con más de un millón de filas, esta consulta generalmente toma menos de 2 ms.
fuente
take
función de uso que proporcionaLIMIT(1)
consultas pero devuelve un solo elemento en lugar de una matriz. Así que no necesitamos invocarlofirst
aquí vamos
rieles camino
uso
o el segundo pensamiento es
uso:
fuente
Couldn't find all Users with 'id': (first, {:offset=>1}) (found 0 results, but was looking for 2)
"RANDOM()"
en su lugar ...Esto fue muy útil para mí, sin embargo, necesitaba un poco más de flexibilidad, así que esto es lo que hice:
Caso 1: Encontrar una fuente de registro aleatorio : sitio trevor turk
Agregue esto al modelo Thing.rb
entonces en tu controlador puedes llamar a algo como esto
Caso 2: Encontrar múltiples registros aleatorios (sin repeticiones) fuente: no puedo recordar
que necesitaba encontrar 10 registros aleatorios sin repeticiones, así que esto es lo que encontré funcionado
en su controlador:
Esto encontrará 10 registros aleatorios, sin embargo, vale la pena mencionar que si la base de datos es particularmente grande (millones de registros), esto no sería ideal y el rendimiento se verá obstaculizado. Se realizará bien hasta unos pocos miles de registros, lo cual fue suficiente para mí.
fuente
El método Ruby para elegir aleatoriamente un elemento de una lista es
sample
. Queriendo crear un eficientesample
para ActiveRecord, y en base a las respuestas anteriores, utilicé:Puse esto
lib/ext/sample.rb
y luego lo cargué con esto enconfig/initializers/monkey_patches.rb
:fuente
#count
hará una llamada a la base de datos para aCOUNT
. Si el registro ya está cargado, esta podría ser una mala idea. Un refactor sería usar#size
en su lugar, ya que decidirá si#count
debe usarse o, si el registro ya está cargado, usar#length
.count
asize
basado en sus comentarios. Más información en: dev.mensfeld.pl/2014/09/…Funciona en Rails 5 y es independiente de DB:
Esto en su controlador:
Por supuesto, puede poner esto en una preocupación como se muestra aquí .
aplicación / modelos / preocupaciones / randomable.rb
luego...
app / models / book.rb
Entonces puede usar simplemente haciendo:
o
fuente
Puede usar sample () en ActiveRecord
P.ej
Fuente: http://thinkingeek.com/2011/07/04/easily-select-random-records-rails/
fuente
sample
no está en ActiveRecord, la muestra está en matriz. api.rubyonrails.org/classes/Array.html#method-i-sampleSi usa Oracle
Salida
fuente
Recomiendo esta gema para registros aleatorios, que está especialmente diseñada para tablas con muchas filas de datos:
https://github.com/haopingfan/quick_random_records
Todas las demás respuestas funcionan mal con una base de datos grande, excepto esta gema:
4.6ms
totalmente.User.order('RAND()').limit(10)
costo de la respuesta aceptada733.0ms
.offset
enfoque costó245.4ms
totalmente.User.all.sample(10)
costo de aproximación573.4ms
.Nota: Mi mesa solo tiene 120,000 usuarios. Cuantos más registros tenga, más enorme será la diferencia de rendimiento.
ACTUALIZAR:
Realizar en la mesa con 550,000 filas
Model.where(id: Model.pluck(:id).sample(10))
costo1384.0ms
gem: quick_random_records
solo cuesta6.4ms
totalmentefuente
Una forma muy fácil de obtener múltiples registros aleatorios de la tabla. Esto hace 2 consultas baratas.
Model.where(id: Model.pluck(:id).sample(3))
Puede cambiar el "3" por la cantidad de registros aleatorios que desee.
fuente
Me encontré con este problema desarrollando una pequeña aplicación en la que quería seleccionar una pregunta aleatoria de mi base de datos. Solía:
Y me está funcionando bien. No puedo hablar sobre el rendimiento de las bases de datos más grandes, ya que esta es solo una pequeña aplicación.
fuente
shuffle[0]
)