it-swarm.com.de

Wie holt man mehr als 1000?

Wie kann ich mehr als 1000 Datensätze aus dem Datenspeicher abrufen und alles in einer einzigen Liste zusammenfassen, um es an Django zu übergeben?

48
Zote

Ab Version 1.3.6 (veröffentlicht am 17. August 2010) können Sie 

Aus dem Änderungsprotokoll:

Ergebnisse von Datastore count () - Abfragen und Offsets für alle Datastore-Abfragen werden nicht mehr auf 1000 begrenzt.

37
Shay Erlichmen

Nur für den Rekord - Abruflimit von 1000 Einträgen ist jetzt weg:

http://googleappengine.blogspot.com/2010/02/app-engine-sdk-131-including-major.html

Zitat:

Keine 1000-Ergebnisgrenze mehr - Das ist Richtig: mit Zusatz von Cursors und Der Höhepunkt vieler kleinerer Datastores Stabilität und Leistung Verbesserungen in den letzten Monaten, Wir sind jetzt zuversichtlich genug, die maximale Ergebnisgrenze insgesamt zu entfernen. Ob Sie einen Abruf durchführen, Iterieren oder einen Cursor verwenden, es gibt einen keine Begrenzung der Anzahl der Ergebnisse.

23

App Engine bietet Ihnen eine nette Möglichkeit, die Ergebnisse um 1000 zu "durchblättern", indem Sie die Keys nacheinander sortieren und den letzten Key als nächsten Offset verwenden. Sie stellen hier sogar Beispielcode zur Verfügung:

http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Queries_on_Keys

Obwohl ihr Beispiel die Abfragen über viele Anforderungen verteilt, können Sie die Seitengröße von 20 bis 1000 ändern und in einer Schleife abfragen, indem Sie die Abfragesätze kombinieren. Zusätzlich können Sie itertools verwenden, um die Abfragen zu verknüpfen, ohne sie vorher auszuwerten.

Um beispielsweise zu zählen, wie viele Zeilen über 1000 hinausgehen:

class MyModel(db.Expando):
    @classmethod
    def count_all(cls):
        """
        Count *all* of the rows (without maxing out at 1000)
        """
        count = 0
        query = cls.all().order('__key__')

        while count % 1000 == 0:
            current_count = query.count()
            if current_count == 0:
                break

            count += current_count

            if current_count == 1000:
                last_key = query.fetch(1, 999)[0].key()
                query = query.filter('__key__ > ', last_key)

        return count
19
JJ Geewax

Bei jeder Einschränkung frage ich mich immer, " warum benötigen Sie mehr als 1.000 Ergebnisse?" Wussten Sie, dass Google selbst nicht mehr als 1.000 Ergebnisse liefert? Versuchen Sie diese Suche: http://www.google.ca/search?hl=de&client=firefox-a&rls=org.mozilla:en-US:official&hs=qhu&q=1000+results&start=1000&sa=N I didn ' Das wußte ich bis vor kurzem nicht, weil ich mir nie die Zeit genommen hatte, auf die 100. Seite der Suchergebnisse einer Abfrage zu klicken.

Wenn Sie tatsächlich mehr als 1.000 Ergebnisse an den Benutzer zurückgeben, ist meiner Meinung nach ein größeres Problem vorhanden, als die Tatsache, dass der Datenspeicher es Ihnen nicht erlaubt.

Ein möglicher (legitimer) Grund, so viele Ergebnisse zu benötigen, ist, wenn Sie die Daten umfangreich bearbeiten und eine Zusammenfassung anzeigen (z. B. den Durchschnitt aller dieser Daten). Die Lösung für dieses Problem (worüber im Google I/O-Gespräch gesprochen wird) besteht darin, die zusammenfassenden Daten im laufenden Betrieb zu berechnen und zu speichern.

18
Tony Arkles

Das kannst du nicht.

Ein Teil der FAQ besagt, dass Sie über die Zeile 1000 einer Abfrage hinaus keinen Zugriff haben. Das Erhöhen des Wertes "OFFSET" führt nur zu einer kürzeren Ergebnismenge. 

dh: OFFSET 999 -> 1 Ergebnis kommt zurück. 

Von Wikipedia: 

App Engine begrenzt die maximalen Zeilen , Die von einem Entity-Get zurückgegeben werden, auf 1000 Zeilen pro Datastore-Aufruf. Die meisten Webanwendungen Verwenden Paging und Zwischenspeicherung und erfordern daher nicht so viele Daten auf einmal, weshalb dies in den meisten Szenarien ein Problem Ist . [Zitat erforderlich] Wenn eine Anwendung mehr als 1.000 Datensätze pro Vorgang benötigt, kann sie ihre eigene clientseitige Software oder eine Ajax-Seite verwenden Führen Sie eine - Operation für eine unbegrenzte Anzahl von Zeilen aus.

Von http://code.google.com/appengine/docs/whatisgoogleappengine.html

Ein anderes Beispiel für ein Dienstlimit ist Die Anzahl der Ergebnisse, die von einer - Abfrage zurückgegeben werden. Eine Abfrage kann höchstens 1.000 Ergebnisse zurückgeben. Abfragen, die Zurückgeben würden, liefern nur das Maximum . In diesem Fall wird eine Anforderung, dass Eine solche Abfrage ausführt, nicht wahrscheinlich vor dem Timeout Eine Anforderung zurückgeben, , Aber die Beschränkung für das Speichern von Ressourcen im Datastore.

Von http://code.google.com/appengine/docs/datastore/gqlreference.html

Hinweis: Eine LIMIT-Klausel hat ein Maximum von 1000. Wenn ein Limit angegeben wird, das größer als das Maximum ist, wird das Maximum Verwendet. Das gleiche Maximum gilt für die Methode Fetch () der GqlQuery-Klasse.

Hinweis: Wie beim Parameter offset für die Methode Der Methode fetch () verringert ein OFFSET in einer GQL-Abfragezeichenfolge Nicht die Anzahl der aus Abgerufenen Entitäten. Datenspeicher. Es beeinflusst nur, welche Ergebnisse von der Methode fetch () Zurückgegeben werden. Eine Abfrage mit einem Offset hat Leistungsmerkmale, die Linear mit der Offsetgröße Übereinstimmen.

Von http://code.google.com/appengine/docs/datastore/queryclass.html

Die Argumente "limit" und "offset" steuern , Wie viele Ergebnisse aus dem - Datastore abgerufen werden und wie viele Von der fetch () - Methode zurückgegeben werden:

  • Der Datenspeicher holt Offset- und Grenzergebnisse für die Anwendung. Die ersten Versatzergebnisse werden vom Datenspeicher selbst nicht übersprungen.

  • Die Methode fetch () überspringt die ersten Versatzergebnisse und gibt dann den Rest zurück (Limit-Ergebnisse).

  • Die Abfrage hat Leistungsmerkmale, die Linear mit dem Versatzbetrag plus dem Grenzwert übereinstimmen.

Was bedeutet das? 

Wenn Sie eine einzelne Abfrage haben, können Sie nichts außerhalb des Bereichs 0-1000 anfordern. 

Durch Erhöhen des Offsets wird nur die 0 erhöht

LIMIT 1000  OFFSET 0    

Gibt 1000 Zeilen zurück, 

und 

LIMIT 1000 OFFSET 1000 

Gibt 0 Zeilen zurück, wodurch es mit einer einzigen Abfragesyntax unmöglich ist, 2000 Ergebnisse entweder manuell oder mithilfe der API abzurufen. 

Die einzige plausible Ausnahme

Soll ein numerischer Index für die Tabelle erstellt werden, dh: 

 SELECT * FROM Foo  WHERE ID > 0 AND ID < 1000 

 SELECT * FROM Foo WHERE ID >= 1000 AND ID < 2000

Wenn Ihre Daten oder Suchabfragen diese ID-ID nicht enthalten können, sind Sie Pech

14
Kent Fredric

Dieses 1K-Limitproblem wurde behoben.

query = MyModel.all()
for doc in query:
    print doc.title

Durch das Behandeln des Query-Objekts als iterierbar: Der Iterator ruft die Ergebnisse aus dem Datenspeicher in kleinen Batches ab. Dadurch kann die App die Iteration der Ergebnisse beenden, um zu vermeiden, dass mehr Informationen abgerufen werden, als benötigt werden. Die Iteration wird beendet, wenn alle Ergebnisse abgerufen wurden, die der Abfrage entsprechen. Wie bei fetch () speichert die Iteratorschnittstelle die Ergebnisse nicht im Cache. Wenn Sie also einen neuen Iterator aus dem Query-Objekt erstellen, wird die Abfrage erneut ausgeführt.

Die maximale Losgröße beträgt 1K. Und Sie haben auch noch die automatischen Datastore-Quoten.

Mit dem Plan 1.3.1 SDK haben sie jedoch Cursor eingeführt, die serialisiert und gespeichert werden können, sodass ein zukünftiger Aufruf die Abfrage dort beginnen kann, wo er zuletzt aufgehört hat.

10
Tiger Woods

Das Limit von 1000 Datensätzen ist ein hartes Limit in Google AppEngine.

In dieser Präsentation http://sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine wird erläutert, wie Sie mit AppEngine Daten effizient durchblättern.

(Im Wesentlichen durch Verwenden einer numerischen ID als Schlüssel und Angabe einer WHERE-Klausel für die ID.)

7
jakber

Das Abrufen über die Remote-API hat immer noch Probleme, wenn mehr als 1000 Datensätze aufgezeichnet werden. Wir haben diese kleine Funktion geschrieben, um in Brocken über eine Tabelle zu iterieren:

def _iterate_table(table, chunk_size = 200):
    offset = 0
    while True:
        results = table.all().order('__key__').fetch(chunk_size+1, offset = offset)
        if not results:
            break
        for result in results[:chunk_size]:
            yield result
        if len(results) < chunk_size+1:
            break
        offset += chunk_size
6
Tzach

wir verwenden etwas in unserer ModelBase-Klasse:

@classmethod
def get_all(cls):
  q = cls.all()
  holder = q.fetch(1000)
  result = holder
  while len(holder) == 1000:
    holder = q.with_cursor(q.cursor()).fetch(1000)
    result += holder
  return result

Dadurch wird die 1000-Abfragegrenze für jedes Modell umgangen, ohne darüber nachdenken zu müssen. Ich denke, eine Schlüsselversion wäre genauso einfach zu implementieren.

3
Gabriel
entities = []
for entity in Entity.all():
    entities.append(entity)

So einfach ist das. Beachten Sie, dass für jede Entität ein RPC erstellt wird, der viel langsamer ist als das Abrufen in Chunks. Wenn Sie sich also Sorgen um die Leistung machen, gehen Sie wie folgt vor:

Wenn Sie weniger als 1 Mio. Artikel haben:

entities = Entity.all().fetch(999999)

Verwenden Sie andernfalls einen Cursor.

Es ist auch zu beachten, dass:

Entity.all().fetch(Entity.all().count())

gibt 1000 max zurück und sollte nicht verwendet werden.

2
crizCraig
class Count(object):
def getCount(self,cls):
    class Count(object):
def getCount(self,cls):
    """
    Count *all* of the rows (without maxing out at 1000)
    """
    count = 0
    query = cls.all().order('__key__')


    while 1:
        current_count = query.count()
        count += current_count
        if current_count == 0:
            break

        last_key = query.fetch(1, current_count-1)[0].key()
        query = query.filter('__key__ > ', last_key)

    return count
2
fun_vit

JJG: Ihre Lösung ist fantastisch, außer dass sie eine Endlosschleife verursacht, wenn Sie 0 Datensätze haben. (Ich habe dies herausgefunden, als ich einige meiner Berichte lokal getestet habe).

Ich habe den Beginn der while-Schleife so geändert, dass er wie folgt aussieht:

while count % 1000 == 0:
    current_count = query.count()
    if current_count == 0:
        break
1
mhawthorne

So fügen Sie den Inhalt der beiden Abfragen zusammen:

list1 = first query
list2 = second query
list1 += list2

Liste 1 enthält jetzt alle 2000 Ergebnisse.

0
Tom Leys

Dies ist nahe an der von Gabriel bereitgestellten Lösung, liefert jedoch nicht die Ergebnisse, sondern zählt sie nur:

count = 0
q = YourEntityClass.all().filter('myval = ', 2)
countBatch = q.count()
while countBatch > 0:
    count += countBatch
    countBatch = q.with_cursor(q.cursor()).count()

logging.info('Count=%d' % count)

Funktioniert perfekt für meine Abfragen und auch schnell (1,1 Sekunden, um 67.000 Entitäten zu zählen)

Beachten Sie, dass es sich bei der Abfrage nicht um einen Ungleichheitsfilter oder eine Gruppe handeln darf, da der Cursor nicht funktioniert und Sie diese Ausnahme erhalten:

AssertionError: Kein Cursor für eine MultiQuery verfügbar (Abfragen mit "IN" - oder "! =" - Operatoren)

0
Timothy Tripp

Wenn Sie NDB verwenden:

@staticmethod
def _iterate_table(table, chunk_size=200):
    offset = 0
    while True:
        results = table.query().order(table.key).fetch(chunk_size + 1, offset=offset)
        if not results:
            break
        for result in results[:chunk_size]:
            yield result
        if len(results) < chunk_size + 1:
            break
        offset += chunk_size
0
Oded Breiner

Die vorgeschlagene Lösung funktioniert nur, wenn Einträge nach Schlüsseln sortiert werden. Wenn Sie zuerst nach einer anderen Spalte sortieren, müssen Sie noch eine Limitklausel (Versatz, Anzahl) verwenden, dann gilt die Einschränkung auf 1000 Einträge. Das Gleiche gilt, wenn Sie zwei Anforderungen verwenden: eine zum Abrufen von Indizes (mit Bedingungen und Sortierung) und eine andere Verwendung von where-Index in () mit einer Teilmenge von Indizes aus dem ersten Ergebnis, da die erste Anforderung nicht mehr als 1000 Schlüssel zurückgeben kann. (Im Abschnitt Google Abfragen zu Schlüsseln wird nicht eindeutig angegeben, ob nach Taste sortiert werden muss , um die Einschränkung auf 1000 Ergebnisse aufzuheben.)

0
cjed