Как получить более 1000? - PullRequest
       17

Как получить более 1000?

48 голосов
/ 05 ноября 2008

Как я могу получить более 1000 записей из хранилища данных и поместить все в один список для передачи в django?

Ответы [ 16 ]

37 голосов
/ 23 августа 2010

Начиная с версии 1.3.6 (выпущена 17 августа 2010 г.) вы CAN

Из журнала изменений:

Результаты запросов count () хранилища данных () и смещений для всех запросов хранилища данных больше не ограничены 1000 .

23 голосов
/ 21 февраля 2010

Только для записи - предел выборки в 1000 записей больше не существует:

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

Цитата:

Не более 1000 результатов - это справа: с добавлением курсоров и кульминация многих меньших Стабильность и производительность хранилища данных улучшения за последние несколько месяцев, теперь мы достаточно уверены, чтобы удалить максимальный предел результата в целом. Делаете ли вы выборку, итерация, или с помощью курсора, есть нет ограничений на количество результатов.

19 голосов
/ 06 апреля 2009

App Engine дает вам хороший способ «пролистать» результаты на 1000, упорядочив ключи и используя последний ключ в качестве следующего смещения. Здесь даже приведен пример кода:

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

Хотя их пример распределяет запросы по многим запросам, вы можете изменить размер страницы с 20 на 1000 и выполнять запросы в цикле, комбинируя наборы запросов. Кроме того, вы можете использовать itertools для связывания запросов без их оценки до того, как они понадобятся.

Например, чтобы посчитать, сколько строк превышает 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
18 голосов
/ 05 ноября 2008

Каждый раз, когда это становится ограничением, я всегда задаюсь вопросом " зачем вам нужно более 1000 результатов?" Знаете ли вы, что сами Google не дают более 1000 результатов? Попробуйте этот поиск: 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 Я не знал этого до недавнего времени, потому что я никогда не тратил время на 100-ю страницу результатов поиска по запросу.

Если вы на самом деле возвращаете более 1000 результатов обратно пользователю, то я думаю, что есть более серьезная проблема, чем тот факт, что хранилище данных не позволит вам это сделать.

Одной из возможных (законных) причин, по которой нужно так много результатов, является то, что вы выполняли большую операцию с данными и представляли сводку (например, каково среднее значение всех этих данных). Решение этой проблемы (о которой говорится в докладе о вводе-выводе Google) состоит в том, чтобы вычислять сводные данные на лету, как они поступают, и сохранять их.

14 голосов
/ 05 ноября 2008

Вы не можете.

В части часто задаваемых вопросов говорится, что вы не можете получить доступ к строке 1000 запроса, и увеличение «OFFSET» приведет к более короткому набору результатов,

т.е.: OFFSET 999 -> 1 результат возвращается.

Из Википедии:

App Engine ограничивает максимальные строки возвращается от лица получить до 1000 строк на вызов хранилища данных. Большинство веб приложения базы данных используют пейджинг и кеширование, а значит и не требует этого много данных одновременно, так что это не проблема в большинстве сценариев. Нужно] Если приложению нужно больше чем 1000 записей за операцию, это может использовать собственное программное обеспечение на стороне клиента или страница Ajax для выполнения операция на неограниченном количестве строки.

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

Другим примером лимита обслуживания является количество результатов, возвращаемых запрос. Запрос может вернуть максимум 1000 результатов. Запросы, которые бы вернуть больше результатов только вернуть максимум. В этом случае запрос, который выполняет такой запрос вряд ли вернуть запрос до истечения времени ожидания, но предел для сохранения ресурсы в хранилище данных.

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

Примечание: предложение LIMIT имеет максимум 1000. Если указан предел, превышающий максимальный, максимальный используемый. Этот же максимум относится к Метод fetch () класса GqlQuery.

Примечание: как параметр смещения для метод fetch (), Смещение в GQL Строка запроса не уменьшает количество объектов, извлеченных из хранилище данных. Это влияет только на которые результаты возвращаются fetch () метод. Запрос со смещением имеет характеристики производительности, которые линейно соответствовать смещению размер.

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

Управление аргументами limit и offset сколько результатов получено из хранилище данных, а сколько возвращается методом fetch ():

  • Хранилище данных получает смещение + ограничение результатов для приложения. Результаты первого смещения не пропущены самим хранилищем данных.

  • Метод fetch () пропускает результаты первого смещения, а затем возвращает остаток (результаты ограничения).

  • Запрос имеет характеристики производительности, которые соответствуют линейно с величиной смещения плюс предел.

Что это значит

Если у вас есть отдельный запрос, нет способа запросить что-либо за пределами диапазона 0-1000.

Увеличение смещения просто поднимет 0, поэтому

LIMIT 1000  OFFSET 0    

Вернет 1000 строк,

и

LIMIT 1000 OFFSET 1000 

Возвращает 0 строк , таким образом, делая невозможным, с одним синтаксисом запроса, получить 2000 результатов либо вручную, либо с помощью API.

Единственное вероятное исключение

Для создания числового индекса в таблице, то есть:

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

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

Если ваши данные или запрос не могут иметь жестко закодированный идентификатор «ID», то вам не повезло

10 голосов
/ 05 февраля 2010

Устранена проблема с лимитом в 1 КБ.

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

Путем обработки объекта Query как итерируемого: итератор получает результаты из хранилища данных небольшими партиями, что позволяет приложению прекратить итерацию по результатам, чтобы избежать выборки больше, чем необходимо. Итерация останавливается, когда все результаты, соответствующие запросу, были получены. Как и в fetch (), интерфейс итератора не кэширует результаты, поэтому создание нового итератора из объекта Query повторно выполнит запрос.

Максимальный размер партии - 1 КБ. И у вас все еще есть автоматические квоты Datastore.

Но в плане 1.3.1 SDK они ввели курсоры, которые можно сериализовать и сохранить, чтобы в будущем вызов мог начать запрос с того места, где он был остановлен в последний раз.

7 голосов
/ 05 ноября 2008

Предел записи 1000 - это жесткий предел в Google AppEngine.

В этой презентации http://sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine объясняется, как эффективно перелистывать данные с помощью AppEngine.

(В основном, используя числовой идентификатор в качестве ключа и указав предложение WHERE для идентификатора.)

6 голосов
/ 01 июля 2014

Выборка, хотя удаленный API все еще имеет проблемы, когда более 1000 записей. Мы написали эту крошечную функцию для перебора таблицы по частям:

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
3 голосов
/ 10 сентября 2010

мы используем что-то в нашем ModelBase классе, а именно:

@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

Это позволяет обойти ограничение в 1000 запросов для каждой модели без необходимости думать об этом. Полагаю, что ключ-версия была бы такой же простой в реализации.

2 голосов
/ 11 августа 2011
entities = []
for entity in Entity.all():
    entities.append(entity)

Все просто. Обратите внимание, что для каждого объекта существует RPC, который намного медленнее, чем выборка кусками. Поэтому, если вы беспокоитесь о производительности, сделайте следующее:

Если у вас менее 1М предметов:

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

В противном случае используйте курсор.

Следует также отметить, что:

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

возвращает максимум 1000 и не должны использоваться.

...