2010-08-17 10 views
33
myqueryset = Content.objects.filter(random 100) 

Respuesta

61
Content.objects.all().order_by('?')[:100] 

Véase el order_by docs. También tenga en cuenta que este enfoque no escala bien (de hecho, escala muy, muy mal). Consulte this SO answer para conocer mejor la selección aleatoria cuando tiene grandes cantidades de datos.

+5

Y el all() es redundante, pero nunca lo recuerdo. – Tom

+0

¡Esto es asombroso! A través de la depuración, he notado que incluso genera una buena consulta, solo tomando 20 elementos, usando 1 consulta, usando ORDER BY RAND() para al azar. Dios mío, eso es fantástico. –

9

Si va a hacer esto más de una vez, debe diseñar esto en su base de datos.

Si lo hace una vez, puede pagar la multa considerable. Esto te da exactamente 100 con propiedades aleatorias realmente buenas. Sin embargo, usa mucha memoria.

pool= list(Content.objects.all()) 
random.shuffle(pool) 
object_list = pool[:100] 

Aquí hay otro algoritmo que también es lento porque puede buscar en toda la tabla. No utiliza mucho la memoria en absoluto y no puede conseguir exactamente 100.

total_count= Content.objects.count() 
fraction = 100./total_count 
object_list = [ c for c in Content.objects.all() if random.random() < fraction ] 

Si quieres hacer esto más de una vez, es necesario agregar un atributo al contenido para permitir el filtrado eficaz para "al azar " valores. Por ejemplo, puedes hacer esto.

class Content(models.Model): 
    ... etc. ... 
    def subset(self): 
     return self.id % 32768 

Esto dividirá sus datos en 32768 subconjuntos distintos. Cada subconjunto es 1/32768'th de sus datos. Para obtener 100 elementos aleatorios, necesita 100 * 32768/subconjuntos total_count de sus datos.

total_count = Content.objects.count() 
no_of_subsets= 100*32768/total_count 
object_list = Content.objects.filter(subset__lte=no_of_subsets) 

Ésta es rápida y es reproducible. Los subconjuntos son "arbitrarios", no técnicamente "aleatorios".

+0

Buen punto para el rendimiento –

+0

Me gusta su último enfoque, aunque no creo que pueda filtrar las propiedades. Tendría que agregar la columna del subconjunto en el modelo en sí y establecer su valor en guardar de esta manera: http://ifacethoughts.net/2009/07/14/calculated-fields-in-django/ – jesal

+0

Añadir subconjunto como método para el modelo de contenido no es suficiente para filtrar, como se sugiere en el último fragmento. –

1

yo: sólo se

import random  
object_list = list(Content.objects.filter(foo=bar).values()[:100]) 
random.shuffle(object_list) 

consulta se ejecuta una sola sencilla MySQL y es bueno en el rendimiento.

+1

Esto no devuelve registros aleatorios de la base de datos. Selecciona el primer centenar de registros y los mezcla. Los registros 101 en adelante no tienen posibilidad de ser seleccionados. – Blair

+0

Quise sugerir el uso de la función de mezcla sobre order_by ('?') Que tiene serios problemas de rendimiento: http://stackoverflow.com/a/6405601/232649 Para mezclar todos los registros: shuffle (list (Content.objects) .all())) [: 100] – Pratyush

Cuestiones relacionadas