9

Мне нравится простота, масштабируемость и простота использования хранилища данных; и улучшения, обнаруженные в новой библиотеке ndb, являются сказочными.ищет идеи/альтернативы предоставлению количества страниц/элементов/навигации элементов, соответствующих запросу хранилища данных GAE

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

Однако во многих приложениях, в том числе и у нас, существует общее желание увидеть количество совпадающих элементов и предоставить пользователю возможность перейти к определенной странице этих результатов. Проблема подкачки хранилища данных еще более усложняется требованием обходить ограничения выборки (предел, смещение = X), как указано в статье Paging Through Large Datasets. Чтобы поддержать рекомендуемый подход, данные должны включать столбцы с уникальной оценкой, которые можно упорядочить так, как должны отображаться результаты. Этот столбец будет определять начальное значение для каждой страницы результатов; экономя его, мы можем получить соответствующую страницу эффективно, позволяя навигацию на определенной или следующей странице по мере необходимости. Поэтому, если вы хотите показать результаты, упорядоченные несколькими способами, возможно, потребуется сохранить несколько таких столбцов.

Следует отметить, что с SDK v1.3.1, Query Cursors рекомендуется использовать подкачку datastore. У них есть некоторые ограничения, в том числе отсутствие поддержки операторов IN и! = Filter. В настоящее время некоторые из наших важных запросов используют IN, но мы попробуем их написать, используя ИЛИ для использования с курсорами запросов.

Следуя инструкциям, предложенных, пользователь может быть дан (Next) и (Prev) навигационные кнопки, а также кнопки конкретные страницы, как навигация протекала. Например, если пользователь нажал (Next) 3 раза, приложение может отображать следующие кнопки, помня о уникальной стартовой записи или курсоре для каждого, чтобы сохранить эффективность навигации: (Pre-) (Страница-1) (Страница-1)) (Страница-3) (Страница-4) (далее).

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

Я ищу идеи по этим вопросам в целом и следующие вопросы конкретно:

  1. Какие навигационных вариантами результатов запроса вы предоставляете в хранилище данных приложений, чтобы работать вокруг этих ограничений?

  2. Если предоставления пользователям эффективных результатов подсчетов и навигации по страницам всего набора результатов запроса является одним из приоритетов, следует использовать в датасторе отказаться в пользу GAE MySql solution сейчас предлагается.

  3. Есть ли какие-либо изменения в архитектуре большой таблицы или реализация хранилища данных, которая обеспечит дополнительную возможность для эффективно подсчет результатов запроса?

Большое спасибо за вашу помощь.

ответ

2

Все зависит от того, сколько результатов вы обычно получите. Например. передав .count() подходящий предел, вы можете предоставить точное количество, если #items, например. < = 100 и «много», если их больше. Похоже, вы не можете предварительно вычислить все возможные значения, но, по крайней мере, вы можете кэшировать их, тем самым сохраняя множество операций хранилища данных.

Использование NDB, наиболее эффективным подходом может быть либо запрос первой страницы сущностей с использованием fetch_page(), а затем использование результирующего курсора в качестве отправной точки для вызова count(); или, альтернативно, вам может быть лучше запускать fetch() первой страницы и count() одновременно с использованием своих асинхронных объектов. Второй вариант может быть вашим единственным выбором, если ваш запрос не поддерживает курсоры. Большинство запросов IN/OR в настоящее время не поддерживают курсоры, но они делают, если вы заказываете __key__.

Что касается параметров пользовательского интерфейса, я думаю, что достаточно предложить следующие и предыдущие параметры страницы; пользовательский интерфейс «Gooooooogle», который позволяет пропустить несколько страниц, симпатичен, но я почти никогда не использую его сам. (Чтобы реализовать «предыдущую страницу», отмените порядок запроса и используйте тот же самый указатель, который вы использовали для текущей страницы. Я уверен, что это гарантированно будет работать.)

+0

Предполагая, что мы используем подход C = query.count (N), чтобы показать пользователю «1-20 из C» или «1-20 из многих», как мы определяем разумную стоимость, затратную для N. В нашем использовании случай 100 будет слишком маленьким. Любые предложения о том, как наилучшим образом оценить это, чтобы сохранить стоимость $ вниз? Из документов NDB: «Обратите внимание, что count(), а быстрее, чем fetch(), все равно выполняет много работы каждый раз, когда он вызывается «Сколько квот используется? Guido, Спасибо за Python, NDB и вашу помощь :) IMO-страницы и навигация - отличная возможность для некоторых приложений, потому что пользователи могут оценивать и корректировать размер данных, соответствующих их параметрам перед сверлением. –

+1

Вы можете вычислить стоимость, используя эту страницу: http://code.google.com/appengine/docs/billing.html#Billable_Resource_Unit_Costs. AFAIK a Count() похож на запрос только для ключей. (в зависимости от про Если у вас ограниченное количество отсчетов для кеширования, вы можете хранить счета в хранилище данных, используя шаблон с зачеркнутым счетчиком.) –

+3

Также обновление по запросам IN/OR: вы можете превратить любой запрос в курсор -поддерживая запрос, добавив заказ __key__ в конце существующего порядка сортировки. Например. в NDB: 'Employee.query (Employee.name.IN (['Joe', 'Jane'])). order (Employee.name, Employee.key) .fetch_page (N)' - без заказа Employee.key он вызывает BadArgumentError. –

0
  1. Я заметил, что Gmail готов с некоторыми подсчетами - это может сказать вам, сколько общего писем вы получили, и сколько в вашем почтовом ящике, и т.д. - но по другим пунктам, как полнотекстовый поиск его говорит, что вы смотрите на «1-20 из многих» или «1-20 около 130». Вам действительно нужно отображать подсчеты для каждого запроса, или вы можете предварительно вычислить только важные?
+0

Отслеживание хорошо известных итогов, безусловно, проще. В некоторых статьях, которые я прочитал, для этого используются люди с заштрихованными счетчиками: GAc: http://code.google.com/appengine/articles/sharding_counters.html. Наш пример использования больше похож на полнотекстовые поисковые запросы в формате gmail. Я думаю, что показ итогов и навигации по страницам позволит пользователям лучше понять их результаты поиска до того, как они просверлится. Это говорит о том, что, если использовать хранилище данных, единственным вариантом является «1-20 из многих» подход, запрещающий некоторые откровения здесь. По-видимому, gmail показывает «1-20 около 130», когда результирующий набор мал, может быть, заглядывая вперед. –

1

Возможно, просто нарисуйте этот стиль подкачки :

(первый) (Назад) (Page1) (Стр.2) (Page3) .... (Last) (следующий)

Таким образом, общее количество не требуется - нужно только код знать, что результатов для других 3+ страниц достаточно. с размером страницы 10 элементов на страницу, вам просто нужно знать, что есть более 30 предметов.

Если у вас есть 60 предметов (достаточно на 6 страниц), когда вы уже на странице 4, ваш код будет смотреть вперед и понимать, что есть только еще 20 записей, чтобы вы могли показать последний номер страницы:

(первый) (Назад) (Page4) (Page5) (Page6) (следующая) (последняя)

в принципе для каждой выборки для текущей страницы, просто получать достаточное количество записей в течение еще 3 страниц данных, посчитайте их, чтобы узнать, сколько еще страниц вы активируете, затем настройте свой пейджер соответственно.

Кроме того, если вы просто забираете ключи, это будет более эффективно, чем выбор дополнительных предметов. желающий что-то смысл !! ​​?? :)

+0

Эй, спасибо за предложение. Вы взяли то, что я описал выше, в пятом параграфе моего первоначального вопроса. Ответ Гвидо заостряет внимание на том, что возможно. Учитывая стоимость запроса на подсчет, для большого набора данных мы обязательно будем использовать что-то вроде «...», когда N меньше общего количества результатов. См. Обсуждение под ответом Гвидо для большего контекста. –

0

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

Я подробно остановился на этом, отвечая на подобный вопрос, вы найдете пример кода там:

Backward pagination with cursor is working but missing an item

Пример кода будет более подходящим для этого вопроса. Вот его часть:

def session_list(): 
    page = request.args.get('page', 0, type=int) 

    sessions_keys = Session.query().order(-Session.time_opened).fetch(100, keys_only=True) 
    sessions_keys, paging = generic_list_paging(sessions_keys, page) 
    # generic_list_paging will select the proper sublist. 
    sessions = [ sk.get() for sk in sessions_keys ] 

    return render_template('generic_list.html', objects=sessions, paging=paging) 

См. Упомянутый вопрос для получения дополнительной информации.

Конечно, если результирующий набор потенциально огромен, то необходимо ограничить выборку, жесткий предел которого составляет 1000 единиц. Очевидно, что результат составляет более 10 страниц, пользователю будет предложено уточнить его, добавив критерии.

Работа с поисковым вызовом в течение нескольких сотен элементов key_only на самом деле намного проще, что, безусловно, стоит рассмотреть. Это позволяет легко обеспечить прямую навигацию по страницам, как указано в вопросе. Фактические объекты объекта выбираются только для текущей текущей страницы, остальные - это только ключи, поэтому это не так дорого. И вы можете подумать о том, чтобы хранить key_only результат в memcache в течение нескольких минут, чтобы пользователь быстро просматривал страницы, не потребует повторного выполнения одного и того же запроса.

Смежные вопросы