2010-06-09 25 views
18

Ich habe einen Datenspeicher mit ungefähr 1.000.000 Entitäten in einem Modell. Ich möchte 10 zufällige Entitäten daraus holen.Abrufen eines zufälligen Datensatzes aus dem Google App Engine-Datenspeicher?

Ich bin mir nicht sicher, wie das geht? Kann jemand helfen?

+0

möglich Duplikat von [Abfrage von N zufälligen Datensätzen auf Appengine Datenspeicher] (http://stackoverflow.com/questions/1105004/querying-for-n-random-records-on-appengine-datastore) –

Antwort

21

Weisen Sie jeder Entität eine Zufallszahl zu und speichern Sie sie in der Entität. Dann Abfrage für zehn Datensätze, deren Zufallszahl größer als (oder kleiner als) eine andere Zufallszahl ist. Diese

ist nicht völlig zufällig, jedoch, da Organisationen in der Nähe von Zufallszahlen werden zusammen zu zeigen, neigen. Wenn Sie das übertreffen wollen, machen Sie zehn Abfragen, die auf zehn Zufallszahlen basieren, aber das wird weniger effizient sein.

+0

Genau richtig. Vielleicht möchte ich den Bereich (0..1 ist Standard) für die Zufallszahlen erwähnen. –

+4

Eine Möglichkeit, die Zufälligkeit zu erhöhen, ohne die Effizienz der Lesezeit zu beeinträchtigen, wäre die Zuweisung neuer Zufallszahlen in die Entitäten, die Sie abgerufen haben. Wenn Sie also eine davon erneut treffen, erhalten Sie nicht die gleichen Nachbarn. – geoffspear

+0

@NickJohnson können Sie über den Standardbereich klären? Entschuldigung, ich habe nicht verstanden, was du mit (0..1) meintest? Auch für Sie beide: Ich mache mir Sorgen über die Verwendung meiner einen Ungleichheitsfilter für diese Operation (weil in einigen Abfragen ich es zufällig sein muss, aber gleichzeitig einen Gleichheitsfilter auf eine andere Eigenschaft ausführen). Wie schlimm ist es 10 Anfragen zu beantworten, ist es im Grunde 10x die Kosten? – iceanfire

3

Jason Halls Antwort und the one here sind nicht schrecklich, aber wie er erwähnt, sind sie auch nicht wirklich zufällig. Selbst zehn Abfragen sind nicht zufällig, wenn zum Beispiel die Zufallszahlen alle zusammen gruppiert sind. Um die Dinge wirklich zufällig, hier sind zwei mögliche Lösungen:

Lösung 1

einen Index zu jedem Datenspeicher-Objekt zuweisen, verfolgen den maximalen Index, und zufällig wählen Sie jedes Mal eine Index, den Sie erhalten möchten ein Zufallsergebnis:

MyObject.objects.filter('index =', random.randrange(0, maxindex+1))

Upside: Wirklich zufällig. Schnell.

Down-Seite: Sie müssen Indizes beim Hinzufügen und Löschen von Objekten richtig pflegen, was beide Operationen zu einer O (N) -Operation machen kann.

Lösung 2

eine Zufallszahl an jede Datenspeicher-Nummer zuweisen, wenn sie erstellt wird. Um dann einen Zufallsdatensatz das erste Mal zu erhalten, fragen Sie nach einem Datensatz mit einer Zufallszahl, die größer als eine andere Zufallszahl ist, und nach den Zufallszahlen (d. H. MyObject.order('rand_num').filter('rand_num >=', random.random())). Speichern Sie dann diese Abfrage als einen Cursor im Memcache. Um nach dem ersten Mal einen zufälligen Datensatz zu erhalten, laden Sie den Cursor aus dem Memcache und gehen Sie zum nächsten Element. Wenn nach dem ersten Element kein Element mehr vorhanden ist, führen Sie die Abfrage erneut aus.

Um zu verhindern, dass sich die Reihenfolge der Objekte bei jedem gelesenen Datenspeicher wiederholt, geben Sie der gerade gelesenen Entität eine neue Zufallszahl und speichern sie wieder im Datenspeicher.

Nach oben: Wahrlich zufällig. Keine komplexen Indizes zu pflegen.

Down-Seite: Sie müssen einen Cursor verfolgen. Sie müssen jedes Mal, wenn Sie eine zufällige Aufzeichnung erhalten, einen Put machen.

+0

"Selbst die Ausführung von zehn Abfragen ist nicht zufällig, wenn zum Beispiel die Zufallszahlen alle zusammen gruppiert sind" - Ich nehme an, Sie sprechen über die Zufallszahlen, die den Datenspeicherzeilen zugewiesen wurden. Dies ist nur ein Problem für eine kleine Anzahl von Datensätzen - die Standardabweichung von Lücken zwischen Werten schrumpft mit steigender Anzahl von Werten bis zu dem Punkt, an dem sie statistisch nicht signifikant ist. Ihre Lösung 1 erfordert einen monotonen Zähler, was eine langsame und teure Operation in App Engine ist. Lösung 2 verwendet Auswahl ohne Ersatz, was sich von dem unterscheidet, was das OP gefordert hat. –

+0

Richtig, der naive Ansatz bricht zusammen, wenn es nicht viele Datensätze gibt oder wenn Sie sie mit einer hohen Rate abrufen. Sobald die Rand_num-Werte festgelegt sind, ist ihre Verteilung festgelegt. Sie erhalten keine gute einheitliche Verteilung und es wird bestimmte Datensätze geben, die nur selten ausgewählt werden. – speedplane

+0

Nein, das war mein Punkt - je größer die Anzahl der Datensätze, die Sie haben, desto kleiner ist die Standardabweichung im Intervall. Das heißt, es wird proportional weniger Entitäten geben, denen abnormal kleine Intervalle zugeordnet sind. Der Vorschlag von Woble, Nummern neu zuzuweisen, sobald Sie einen Datensatz auswählen, würde dem ebenfalls entgegenwirken. –

Verwandte Themen