¿Cómo buscar más de 1000?
-
06-07-2019 - |
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?
Solución
A partir de la versión 1.3.6 (lanzada el 17 de agosto de 2010) usted PUEDE
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