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

Antwort

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

Siehe order_by docs. Beachten Sie auch, dass dieser Ansatz nicht gut skaliert (tatsächlich skaliert er wirklich sehr schlecht). Siehe this SO answer für eine bessere Möglichkeit zur zufälligen Auswahl, wenn Sie große Datenmengen haben.

+5

Und die all() ist redundant, aber ich erinnere mich nie daran. – Tom

+0

Das ist großartig! Durch das Debugging habe ich festgestellt, dass es sogar eine gute Abfrage generiert, die nur 20 Elemente mit einer Abfrage erfasst und ORDER BY RAND() für zufällige Abfragen verwendet. Guter Gott, das ist fantastisch. –

9

Wenn Sie dies mehr als einmal tun, müssen Sie dies in Ihrer Datenbank entwerfen.

Wenn Sie es einmal tun, können Sie es sich leisten, die saftige Strafe zu bezahlen. Dies bringt Sie genau 100 mit wirklich guten zufälligen Eigenschaften. Es benötigt jedoch viel Speicher.

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

Hier ist ein weiterer Algorithmus, der auch langsam ist, da er die gesamte Tabelle durchsuchen kann. Es ist nicht sehr viel Speicher überhaupt verwenden und es kann nicht genau 100.

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

bekommen Wenn Sie mehr als einmal tun wollen, müssen Sie ein Attribut hinzufügen, zum Inhalt für „random effektive Filterung zu ermöglichen "Werte. Zum Beispiel könnten Sie dies tun.

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

Dies wird Ihre Daten in 32768 verschiedene Untergruppen partitionieren. Jede Teilmenge ist 1/32768'th Ihrer Daten. Um 100 zufällige Elemente zu erhalten, benötigen Sie 100 * 32768/total_count-Teilmengen Ihrer Daten.

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

Dies ist schnell und es ist reproduzierbar. Die Teilmengen sind "willkürlich", nicht technisch "zufällig".

+0

Guter Punkt für die Leistung –

+0

Ich mag Ihren letzten Ansatz, obwohl ich glaube nicht, dass Sie auf Eigenschaften filtern können. Sie müssten die Teilmengenspalte im Modell selbst hinzufügen und ihren Wert wie folgt auf Speichern setzen: http://ifacethoughts.net/2009/07/14/calculated-fields-in-django/ – jesal

+0

Teilmenge als Methode hinzufügen Das Content-Modell reicht nicht aus, um es zu filtern, wie es in Ihrem letzten Snippet vorgeschlagen wurde. –

1

ich tun:

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

Läuft nur Einzel einfache MySQL-Abfrage und ist auf die Leistung gut.

+1

Dies liefert keine zufälligen Datensätze aus der Datenbank. Es nimmt die ersten hundert Aufnahmen und mischt sie. Datensätze ab 101 haben keine Chance, ausgewählt zu werden. – Blair

+0

Ich wollte die Verwendung der Shuffle-Funktion über order_by ('?') Vorschlagen, die schwerwiegende Leistungsprobleme hat: http://stackoverflow.com/a/6405601/232649 Zum Mischen aller Datensätze: shuffle (Liste (Content.objects .all())) [: 100] – Pratyush