¿Cómo obtener más de 1000?

¿Cómo puedo obtener más de 1000 registros del almacén de datos y poner todo en una sola lista para pasar a django?

A partir de la versión 1.3.6 (lanzada el 17 de agosto de 2010), PUEDE

Desde el registro de cambios:

Los resultados de las consultas de conteo de datos () y las compensaciones de todas las consultas de datos ya no se limitan a 1000 .

Solo para el registro: el límite de captura de 1000 entradas ahora se ha ido:

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

Cotización:

No más de un límite de resultados de 1000. Eso es correcto: con la adición de Cursores y la culminación de muchas mejoras de rendimiento y estabilidad de Datastore más pequeñas en los últimos meses, ahora tenemos la confianza suficiente para eliminar el límite máximo de resultados. Ya sea que esté realizando una búsqueda, iterando o usando un Cursor, no hay límites en la cantidad de resultados.

App Engine te ofrece una forma agradable de “paginar” a través de los resultados por 1000 al ordenar las teclas y usar la última tecla como la siguiente compensación. Incluso proporcionan algunos ejemplos de código aquí:

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

Aunque su ejemplo distribuye las consultas en muchas solicitudes, puede cambiar el tamaño de la página de 20 a 1000 y consultar en un bucle, combinando los conjuntos de consultas. Además, puede usar itertools para vincular las consultas sin evaluarlas antes de que sean necesarias.

Por ejemplo, para contar cuántas filas más allá de 1000:

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 

Cada vez que esto surge como una limitación, siempre me pregunto ” ¿por qué necesita más de 1,000 resultados?” ¿Sabías que los propios Google no ofrecen más de 1,000 resultados? Pruebe esta búsqueda: http://www.google.ca/search?hl=en&client=firefox-a&rls=org.mozilla:en-US:official&hs=qhu&q=1000+results&start=1000&sa=N No lo supe hasta recientemente, porque nunca me había tomado el tiempo de hacer clic en la página 100 de resultados de búsqueda en una consulta.

Si realmente está devolviendo más de 1,000 resultados al usuario, entonces creo que hay un problema mayor que el hecho de que el almacén de datos no le permita hacerlo.

Una posible (legítima) razón para necesitar tantos resultados es si estaba realizando una gran operación con los datos y presentando un resumen (por ejemplo, cuál es el promedio de todos estos datos). La solución a este problema (de lo que se habla en la charla de Google I / O) es calcular los datos de resumen sobre la marcha, y guardarlos.

Usted no puede

Parte de las preguntas frecuentes indica que no hay forma de que pueda acceder más allá de la fila 1000 de una consulta, boost la “COMPENSACIÓN” solo resultará en un conjunto de resultados más corto,

Es decir: OFFSET 999 -> 1 resultado vuelve.

De Wikipedia:

App Engine limita el número máximo de filas devueltas de una entidad a 1000 filas por llamada a Datastore. La mayoría de las aplicaciones de bases de datos web utilizan paginación y almacenamiento en caché, y por lo tanto no requieren tanta información a la vez, por lo que no es un problema en la mayoría de los escenarios. [Cita requerida] Si una aplicación necesita más de 1,000 registros por operación, puede usar su propio software del lado del cliente o una página Ajax para realizar una operación en un número ilimitado de filas.

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

Otro ejemplo de un límite de servicio es el número de resultados devueltos por una consulta. Una consulta puede devolver como máximo 1.000 resultados. Las consultas que arrojen más resultados solo devuelven el máximo. En este caso, no es probable que una solicitud que realiza una consulta de este tipo devuelva una solicitud antes del tiempo de espera, pero el límite está en su lugar para conservar los recursos en el almacén de datos.

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

Nota: Una cláusula LIMIT tiene un máximo de 1000. Si se especifica un límite mayor que el máximo, se usa el máximo. Este mismo máximo se aplica al método fetch () de la clase GqlQuery.

Nota: al igual que el parámetro de desplazamiento para el método fetch (), un DESPLAZAMIENTO en una cadena de consulta GQL no reduce el número de entidades extraídas del almacén de datos. Solo afecta a los resultados que devuelve el método fetch (). Una consulta con un desplazamiento tiene características de rendimiento que se corresponden linealmente con el tamaño del desplazamiento.

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

Los argumentos de límite y desplazamiento controlan cuántos resultados se recuperan del almacén de datos y cuántos son devueltos por el método fetch ():

  • El almacén de datos recupera los resultados de offset + limit a la aplicación. El primer almacén de datos no omite los primeros resultados de compensación.

  • El método fetch () omite los primeros resultados de compensación, luego devuelve el rest (limitar los resultados).

  • La consulta tiene características de rendimiento que se corresponden linealmente con la cantidad de compensación más el límite.

Lo que esto significa es

Si tiene una consulta singular, no hay forma de solicitar nada fuera del rango 0-1000.

El aumento de la compensación solo elevará el 0, por lo que

 LIMIT 1000 OFFSET 0 

Devolverá 1000 filas,

y

 LIMIT 1000 OFFSET 1000 

Devolverá 0 filas , por lo tanto, haciendo imposible, con una sola syntax de consulta, obtener resultados de 2000 manualmente o utilizando la API.

La única excepción plausible

Es crear un índice numérico en la tabla, es decir:

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

Si sus datos o consultas no pueden tener este identificador codificado en 'ID', entonces no tiene suerte

Este problema de límite de 1 K se resuelve.

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

Al tratar el objeto Query como un iterable: el iterador recupera los resultados del almacén de datos en lotes pequeños, lo que permite que la aplicación deje de iterar los resultados para evitar obtener más datos de los necesarios. La iteración se detiene cuando todos los resultados que coinciden con la consulta se han recuperado. Al igual que con fetch (), la interfaz del iterador no almacena en caché los resultados, por lo que la creación de un nuevo iterador desde el objeto de consulta volverá a ejecutar la consulta.

El tamaño máximo del lote es 1K. Y usted todavía tiene las cuotas automáticas del almacén de datos también.

Pero con el plan 1.3.1 SDK, han introducido cursores que pueden ser serializados y guardados para que una invocación futura pueda comenzar la consulta donde se dejó la última vez.

El límite de registro de 1000 es un límite duro en Google AppEngine.

Esta presentación http://sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine explica cómo navegar de manera eficiente a través de los datos usando AppEngine.

(Básicamente, utilizando una identificación numérica como clave y especificando una cláusula WHERE en la identificación).

Recuperando a través de la API remota todavía tiene problemas cuando más de 1000 registros. Escribimos esta pequeña función para iterar sobre una tabla en trozos:

 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 

Estamos usando algo en nuestra clase ModelBase que es:

 @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 

Esto evita el límite de 1000 consultas en todos los modelos sin tener que pensar en ello. Supongo que una versión de teclas sería igual de fácil de implementar.

 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 
 entities = [] for entity in Entity.all(): entities.append(entity) 

Simple como eso. Tenga en cuenta que hay un RPC creado para cada entidad que es mucho más lento que la captura en trozos. Entonces, si te preocupa el rendimiento, haz lo siguiente:

Si tienes menos de 1M artículos:

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

De lo contrario, utilice un cursor.

También debe tenerse en cuenta que:

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

devuelve 1000 max y no debe utilizarse.

JJG: tu solución anterior es impresionante, excepto que causa un bucle infinito si tienes 0 registros. (Descubrí esto mientras probaba algunos de mis informes localmente).

Modifiqué el inicio del bucle while para que se viera así:

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

Para agregar los contenidos de las dos consultas juntas:

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

La lista 1 ahora contiene todos los 2000 resultados.

La solución propuesta solo funciona si las entradas se ordenan por clave … Si primero se clasifica por otra columna, aún tiene que usar una cláusula de límite (desplazamiento, conteo), entonces la limitación de 1000 entradas aún se aplica. ¿Es lo mismo si usa dos solicitudes: una para recuperar índices (con condiciones y ordenación) y otra usando donde índice en () con un subconjunto de índices del primer resultado, ya que la primera solicitud no puede devolver más de 1000 claves? (La sección de consultas de Google sobre claves no se establece claramente si tenemos que ordenar por clave para eliminar la limitación de 1000 resultados)

Esto está cerca de la solución provista por Gabriel, pero no obtiene los resultados, solo los cuenta:

 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) 

Funciona perfectamente para mis consultas, y también rápido (1.1 segundos para contar con 67,000 entidades)

Tenga en cuenta que la consulta no debe ser un filtro de desigualdad o un conjunto o el cursor no funcionará y obtendrá esta excepción:

AssertionError: No hay cursor disponible para una MultiQuery (consultas usando operadores “IN” o “! =”)

Si estás utilizando NDB:

 @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