python - issue - jira rest api example
¿Cómo buscar más de 1000? (16)
A partir de la versión 1.3.6 (publicada el 17 de agosto de 2010) PUEDE
Los resultados de las consultas y compensaciones del conteo de datos () para todas las consultas del almacén de datos ya no tienen un límite 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?
App Engine le ofrece una buena forma de "buscar" los resultados en 1000 ordenando Llaves y utilizando 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 extiende las consultas sobre muchas solicitudes, puede cambiar el tamaño de página de 20 a 1000 y consultar en un bucle, combinando los conjuntos de consulta. 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 aparece como una limitación, siempre me pregunto " ¿por qué necesitas más de 1,000 resultados?" ¿Sabías que Google 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&sa=N No sabía eso hasta que 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 en realidad le devuelve más de 1000 resultados al usuario, entonces creo que hay un problema mayor 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 realizaba una operación grande sobre los datos y presentaba 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 Google I / O) es calcular los datos de resumen sobre la marcha, tal como vienen, y guardarlos.
El límite de 1000 registros es un límite estricto en Google App Engine.
Esta presentación http://sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine explica cómo hacer una búsqueda eficiente de los datos con AppEngine.
(Básicamente, usando una identificación numérica como clave y especificando una cláusula WHERE en la identificación.)
Este problema de límite 1K está resuelto.
query = MyModel.all()
for doc in query:
print doc.title
Al tratar el objeto Query como 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 en los resultados para evitar obtener más de lo necesario. La iteración se detiene cuando se recuperan todos los resultados que coinciden con la consulta. Al igual que con fetch (), la interfaz del iterador no almacena los resultados en caché, por lo que la creación de un nuevo iterador a partir del objeto Query ejecutará nuevamente la consulta.
El tamaño máximo de lote es 1K. Y todavía tienes las cuotas automáticas de Datastore también.
Pero con el plan 1.3.1 SDK, introdujeron cursores que pueden ser serializados y guardados para que una invocación futura pueda comenzar la consulta donde la dejó por última vez.
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 67,000 entidades)
Tenga en cuenta que la consulta no debe ser un filtro de desigualdad o un conjunto o que el cursor no funcionará y obtendrá esta excepción:
AssertionError: no hay cursor disponible para MultiQuery (consultas con operadores "IN" o "! =")
JJG: tu solución de arriba es increíble, excepto que causa un bucle infinito si tienes 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
La recuperación de 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
La solución propuesta solo funciona si las entradas están ordenadas por clave ... Si primero ordena por otra columna, aún debe usar una cláusula de límite (compensación, recuento), y luego se aplicará la limitación de 1000 entradas. Es lo mismo si usa dos solicitudes: una para recuperar índices (con condiciones y ordenar) y otra usando donde index in () 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 indica claramente si debemos ordenar por clave para eliminar la limitación de 1000 resultados)
Para agregar el contenido de las dos consultas juntas:
list1 = first query
list2 = second query
list1 += list2
La Lista 1 ahora contiene todos los 2000 resultados.
Si estás usando 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
Solo para el registro: el límite de búsqueda de 1000 entradas ya no está:
http://googleappengine.blogspot.com/2010/02/app-engine-sdk-131-including-major.html
Cotización:
No más de 1000 límites de resultados: eso es correcto: con la adición de Cursores y la culminación de muchas mejoras más pequeñas de estabilidad y rendimiento del Almacén de datos en los últimos meses, ahora tenemos la confianza suficiente para eliminar por completo el límite máximo de resultados. Ya sea que esté haciendo una búsqueda, iterando o usando un Cursor, no hay límites en la cantidad de resultados.
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 supera el límite de 1000 consultas en cada modelo sin tener que pensar en ello. Supongo que una versión de claves sería igual de fácil de implementar.
No puedes.
Parte de las preguntas frecuentes indica que no hay forma de que pueda acceder más allá de la fila 1000 de una consulta, aumentar el "DESPLAZAMIENTO" solo resultará en un conjunto de resultados más corto,
es decir: OFFSET 999 -> 1 resultado regresa.
De la Wikipedia:
App Engine limita las filas máximas devueltas desde una entidad a 1000 filas por llamada de 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 esta cantidad de datos a la vez, por lo que esto 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 de 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 la cantidad de resultados devueltos por una consulta. Una consulta puede devolver como máximo 1,000 resultados. Las consultas que devolverían más resultados solo devolverían el máximo. En este caso, una solicitud que realiza dicha consulta no es probable que 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 utiliza 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 compensación para el método fetch (), un DESPLAZAMIENTO en una cadena de consulta GQL no reduce el número de entidades recuperadas del almacén de datos. Solo afecta 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 de desplazamiento.
Desde http://code.google.com/appengine/docs/datastore/queryclass.html
Los argumentos de límite y desplazamiento controlan cuántos resultados se obtienen del almacén de datos y cuántos devuelve el método fetch ():
El almacén de datos obtiene los resultados de desplazamiento + límite a la aplicación. Los primeros resultados de compensación no son omitidos por el mismo 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 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 desplazamiento creciente aumentará el 0, por lo tanto
LIMIT 1000 OFFSET 0
Devolverá 1000 filas,
y
LIMIT 1000 OFFSET 1000
Devolverá 0 filas , lo que imposibilitará, con una sola sintaxis de consulta, obtener los 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 de ''ID'' codificado, entonces no tiene suerte
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 ir a buscar en trozos. 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 se debe tener en cuenta que:
Entity.all().fetch(Entity.all().count())
devuelve 1000 max y no debe usarse.