Как получить n-ую запись запроса хранилища данных
Предположим, что у меня есть модель Foo в GAE и этот запрос:
query = Foo.all (). order ('-ключ')
Я хочу получить n-ую запись. Какой самый эффективный способ добиться этого?
Будет ли решение сломано, если свойство упорядочения не уникально, например, как показано ниже:
query = Foo.all (). order ('-color')
редактировать: n > 1000
редактировать 2: я хочу разработать дружественный механизм подкачки страниц, который показывает доступные страницы (такие как страница 1, страница 2, ... страница 185) и требует "?page=x" в строке запроса вместо "? закладки" =XXX". Когда page = x, запрос должен извлечь записи, начиная с первой записи этой страницы.
2 ответа
Нет эффективного способа сделать это - ни в одной СУБД. В любом случае вы должны по крайней мере последовательно читать записи индекса, пока не найдете n-й, а затем найти соответствующую запись данных. Это более или менее то, что fetch(count, offset) делает в GAE, с дополнительным ограничением в 1000 записей.
Лучший подход к этому - сохранить "закладку", состоящую из значения поля, в котором вы упорядочиваете последнюю полученную вами сущность, и ее ключа. Затем, когда вы хотите продолжить с того места, на котором остановились, вы можете добавить значение поля в качестве нижней границы запроса неравенства и пропустить записи, пока не совпадете или не превысите последний, который вы видели.
Если вы хотите предоставить "дружественные" смещения страниц пользователям, вы можете использовать memcache для хранения связи между начальным смещением и кортежем закладки (order_property, key). При создании страницы вставьте или обновите закладку для сущности, следующей за последней. Когда вы выбираете страницу, используйте закладку, если она существует, или сгенерируйте ее сложным способом, выполняя запросы со смещениями - возможно, несколько запросов, если смещение достаточно велико.
Документацию для класса Query можно найти по адресу: http://code.google.com/appengine/docs/python/datastore/queryclass.html
Класс запросов обеспечивает выборку, которая принимает предел и смещение в вашем случае 1 и n
Время выполнения выборки растет линейно со смещением + предел
поэтому единственный способ оптимизации в вашем случае - убедиться, что записи, к которым вы хотите получить доступ чаще всего, ближе к началу массива.
Вы можете использовать query.filter('key = ', n) query.get()
который вернул бы первое совпадение с ключом n