Согласно документации, функция map
поддерживает все ключевые слова параметров запроса. . Однако я не могу создать значения cursor
и has_more
, используя карту. Как ты это делаешь? Если я использую fetch
для создания result
, cursor
и has_more
, я больше не могу использовать map
, так как он не работает с простыми списками.
Как создать курсор с картой NDB
Ответы (1)
Вы не можете получить курсор из map() — единственный способ получить курсор — это использовать QueryIterator или вызвать fetch_page() (который использует QueryIterator внутри). Флаг has_more доступен только с помощью fetch_page().
Если у вас есть простой список, используйте встроенную функцию map() Python:
map(<function>, <list-of-entries>)
Но, возможно, вы могли бы рассказать нам больше о том, что вы пытаетесь сделать?
person
Guido van Rossum
schedule
04.04.2012
Спасибо за Ваш ответ. В основном я загружаю страницу из 20 комментариев, и для каждого из этих комментариев я хочу загрузить страницу из 5 подкомментариев (желательно параллельно). Мне нужны курсоры как для комментариев, так и для подкомментариев, чтобы я мог загружать больше по запросу. У меня есть рабочее решение, использующее последовательный подход, но у меня сложилось впечатление, что это можно сделать параллельно.
- person Klaus Byskov Pedersen; 10.04.2012
@guido правильно ли работает встроенная в Python функция map() с тасклетами, как это делает query.map()?
- person Robert Kluin; 05.06.2012
@robert: что вообще означает корректная работа map() с тасклетами? Он ничего не знает о тасклетах, поэтому, если вы сопоставите тасклет со списком объектов, вы получите обратно список фьючерсов. Я бы посчитал это правильным. :-)
- person Guido van Rossum; 07.06.2012
@guido, я плохо выразился. ;) То, что я на самом деле хотел спросить, было более тонким. По сути, я пытался спросить и получить подтверждение того, что использование встроенной карты приводит к запуску тасклетов с той же степенью параллелизма (параллелизм rpc), что и при использовании query.map. В моем коде я использую fetch_page в сочетании со встроенной картой, а затем переназначаю этот список, вызывая get_result() для фьючерсов. Кажется делает то, что я хочу.
- person Robert Kluin; 07.06.2012
Эх. :-) Ну, почти во всех случаях вызов асинхронного метода вообще не занимает времени - он просто создает Future и ставит в очередь вызов, который позже запускает тело асинхронного метода. Это связано с тем, что реализация тасклета использует генератор — вызов генератора немедленно возвращает значение, и тело функции не начинает выполняться до тех пор, пока вы не вызовете для него метод next(). (Попробуйте это!) Таким образом, вызов map() для списка из N значений немедленно дает вам список N фьючерсов, а в качестве побочного эффекта добавляет N обратных вызовов в цикл обработки событий.
- person Guido van Rossum; 08.06.2012
PS. Оптимальный способ запуска этих обратных вызовов — использовать yield в списке фьючерсов, чтобы они могли максимально смешаться. Вызов get_result() N раз менее оптимален, особенно если могут быть другие тасклеты в полете (а обычно так и есть -- большинство операций внутренне используют дополнительные тасклеты, например, управление кешем). Наконец, причина, о которой я говорил чуть ли не в первой строке предыдущего комментария, заключается в том, что можно украсить не-генератор-функцию с помощью @ndb.tasklet. Те бегут сразу. (Если бы такая функция называлась get_result(), мне пришлось бы пристрелить автора. :-)
- person Guido van Rossum; 08.06.2012
Круто, совет о доходности — это точно то, что мне было интересно после того, как я поковырялся! Спасибо.
- person Robert Kluin; 11.06.2012