Как создать курсор с картой NDB

Согласно документации, функция map поддерживает все ключевые слова параметров запроса. . Однако я не могу создать значения cursor и has_more, используя карту. Как ты это делаешь? Если я использую fetch для создания result, cursor и has_more, я больше не могу использовать map, так как он не работает с простыми списками.


person Klaus Byskov Pedersen    schedule 03.04.2012    source источник


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