Pregunta

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

¿Fue útil?

Solución

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

Del registro de cambios:

  

Los resultados de las consultas de conteo de datos () y las compensaciones para todas las consultas de almacenamiento de datos ya no tienen un límite de 1000 .

Otros consejos

Solo para el registro: el límite de recuperación de 1000 entradas ya no existe:

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

Cita:

  

No más límite de 1000 resultados - Eso es   derecha: con la adición de cursores y   la culminación de muchos más pequeños   Estabilidad y rendimiento del almacén de datos   mejoras en los últimos meses,   ahora tenemos la confianza suficiente para eliminar   El límite máximo de resultados por completo.   Si estás haciendo una búsqueda,   iterando, o usando un cursor, hay   sin límites en el número de resultados.

App Engine le ofrece una buena forma de "paginación" a través de los resultados en 1000 ordenando en Keys y usando la última clave como el próximo desplazamiento. Incluso proporcionan un código de muestra aquí:

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

Aunque su ejemplo distribuye las consultas entre muchas solicitudes, puede cambiar el tamaño de la página de 20 a 1000 y realizar consultas 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 se presenta como una limitación, siempre me pregunto " ¿por qué necesitas más de 1,000 resultados?" ¿Sabías que Google en sí no ofrece 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 & amp; sa = N No lo sabía hasta hace poco, 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 en realidad está devolviendo más de 1,000 resultados al usuario, entonces creo que hay un problema más grande que el hecho de que el almacén de datos no le permitirá hacerlo.

Una posible razón (legítima) para necesitar tantos resultados es si estaba haciendo una operación grande en los datos y presentando un resumen (por ejemplo, cuál es el promedio de todos estos datos). La solución a este problema (del que se habla en la charla de E / S de Google) es calcular los datos de resumen sobre la marcha, tal como vienen, y guardarlos.

No puedes.

Parte de las preguntas frecuentes establece que no hay forma de que pueda acceder más allá de la fila 1000 de una consulta, lo que aumenta el '' DESPLAZAMIENTO '' solo dará como resultado un conjunto de resultados más corto,

es decir: OFFSET 999 - > 1 resultado vuelve.

De Wikipedia:

  

App Engine limita las filas máximas   devuelto de una entidad llegar a 1000   filas por llamada al almacén de datos. Más web   las aplicaciones de bases de datos usan paginación y   almacenamiento en caché, y por lo tanto no requieren esto   muchos datos a la vez, así que este es un   sin problema en la mayoría de los escenarios. [cita   necesario] 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 un   operación en un número ilimitado de   filas.

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

  

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

De http://code.google.com/appengine/docs/ almacén de datos / gqlreference.html

  

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

     

Nota: como el parámetro offset para   el método fetch (), un OFFSET en un GQL   la cadena de consulta no reduce el   cantidad de entidades obtenidas del   Almacén de datos. Solo afecta a cuales   los resultados son devueltos por fetch ()   método. Una consulta con un desplazamiento tiene   características de rendimiento que   corresponder linealmente con el desplazamiento   tamaño.

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

  

El control de argumentos de límite y desplazamiento   cuántos resultados se obtienen del   almacén de datos y cuántos se devuelven   por el método fetch ():

     
      
  • El almacén de datos obtiene resultados de desplazamiento + límite a la aplicación. Los primeros resultados de desplazamiento no se omiten en el almacén de datos.

  •   
  • El método fetch () omite los primeros resultados de desplazamiento, luego devuelve el resto (resultados límite).

  •   
  • La consulta tiene características de rendimiento que 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, así que

LIMIT 1000  OFFSET 0    

Devolverá 1000 filas,

y

LIMIT 1000 OFFSET 1000 

Devuelve 0 filas , lo que hace que sea imposible, con una sintaxis de consulta única, obtener 2000 resultados 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 consulta no pueden tener este identificador codificado 'ID', entonces está fuera de suerte

Este problema de límite de 1K está resuelto.

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 pequeños lotes, lo que permite que la aplicación deje de repetir los resultados para evitar obtener más de lo necesario. La iteración se detiene cuando se han recuperado todos los resultados que coinciden con la consulta. Al igual que con fetch (), la interfaz del iterador no almacena en caché los resultados, por lo que crear un nuevo iterador desde el objeto Query volverá a ejecutar la consulta.

El tamaño de lote máximo es 1K. Y 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 se pueden serializar y guardar para que una futura invocación pueda comenzar la consulta donde se quedó por última vez.

El límite de 1000 registros es un límite estricto en Google AppEngine.

Esta presentación http: / /sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine explica cómo desplazarse por los datos de manera eficiente utilizando AppEngine.

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

Obteniendo aunque la API remota todavía tiene problemas cuando hay más de 1000 registros. Escribimos esta pequeña función para iterar sobre una tabla en fragmentos:

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 cada modelo sin tener que pensarlo. Supongo que una versión de claves 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 hecho para cada entidad que es mucho más lento que buscar fragmentos. Entonces, si le preocupa el rendimiento, haga lo siguiente:

Si tiene menos de 1 millón de elementos:

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

De lo contrario, use un cursor.

También debe tenerse en cuenta que:

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

devuelve 1000 max y no debe usarse.

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

Modifiqué el inicio del ciclo while para que se vea así:

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

Para agregar el contenido de las dos consultas juntas:

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

La Lista 1 ahora contiene todos los resultados de 2000.

La solución propuesta solo funciona si las entradas se ordenan por clave ... Si está ordenando por otra columna primero, todavía tiene que usar una cláusula de límite (compensación, recuento), luego se aplica la limitación de 1000 entradas. Es lo mismo si usa dos solicitudes: una para recuperar índices (con condiciones y clasificación) y otra usando where index in () con un subconjunto de índices desde el primer resultado, ya que la primera solicitud no puede devolver más de 1000 claves. (La sección de Google Consultas sobre claves no indica 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 rápido también (1.1 segundos para contar 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 MultiQuery (consultas que utilizan operadores '' IN '' o ''! = ")

Si está 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top