Конструктор запросов NDB не работает должным образом

У меня есть следующий запрос в моем приложении

query = cls.query().filter(cls.taskgroup_id == taskgroup_id, cls.availability == True, cls.task_id > min_task_id).order(cls.task_id) query.fetch(1)

Выше работает нормально, как и ожидалось. (Выбирает только те объекты, которые соответствуют taskgroup_id и доступны, и task_id > min_task_id)

Однако, когда я разбиваю запрос на несколько операторов.

query = cls.query()
query.filter(cls.taskgroup_id == taskgroup_id)
query.filter(cls.availability == True)
query.filter(cls.task_id > min_task_id)

Это не работает, как ожидалось.

Когда я запускаю [2], формирование запроса разбито на несколько операторов, он возвращает мне сущность, доступность которой равна False, а task_id равен min_task_id.

[2] работает не так, как ожидалось (или так, как я ожидаю). Я думаю, что здесь ошибка пользователя. Интересно, что это такое.


person user462455    schedule 19.11.2016    source источник


Ответы (1)


Из Фильтрация по значениям свойств (выделено мной):

query = Account.query(Account.userid >= 40, Account.userid < 50)

[...]

Вместо того, чтобы указывать весь фильтр запроса в одном выражении, вам может быть удобнее построить его пошагово: например:

appengine/standard/ndb/ запросы/snippets.py

query1 = Account.query()  # Retrieve all Account entitites
query2 = query1.filter(Account.userid >= 40)  # Filter on userid >= 40
query3 = query2.filter(Account.userid < 50)  # Filter on userid < 50 too

query3 эквивалентна переменной query из предыдущего примера. Обратите внимание, что объекты запросов являются неизменяемыми, поэтому построение query2 не влияет на query1, а построение query3 не влияет на query1 или query2.

Другими словами, для вашего примера ни один из операторов query.filter() фактически не изменяет query.

Просто присвойте результаты операторов локальным переменным и используйте их, как в приведенном примере.

person Dan Cornilescu    schedule 19.11.2016
comment
Интересно. Не знал, что объекты запроса неизменяемы. Интересно, в чем причина этого. Присвоение результатов временным переменным (хотя и решает проблему), на мой взгляд, делает его уродливым (я могу ошибаться, и, я думаю, для этого есть веская причина). - person user462455; 19.11.2016
comment
Во-первых, это дает возможность создавать один или несколько связанных запросов с одним или несколькими фильтрами, добавленными условно (например, фильтры, настраиваемые и выбираемые пользователем через графический интерфейс). Если бы запрос не был неизменяемым, запросы должны были бы создаваться с нуля повсюду в потенциально сложной условной логике - ИМХО, не являющейся DRY и более подверженной ошибкам. - person Dan Cornilescu; 19.11.2016
comment
Интересно. Я подумал, советуя создавать временные переменные, потому что неизменяемость так же подвержена ошибкам. Очень часто можно увидеть ошибки, в которых вместо запроса2 будет использоваться запрос1 (запрос3 = запрос1.фильтр() вместо запроса2.фильтр(). И поскольку это логическая ошибка, отладка займет больше времени. время, чем ожидалось Было бы лучше, если бы они предоставили изменяемый объект запроса, точно так же, как Java предоставляет StringBuilder (изменяемый) вместе со String (неизменный) - person user462455; 19.11.2016
comment
Если вы не планируете повторно использовать какие-либо промежуточные запросы, просто используйте одно и то же имя переменной каждый раз. - person Greg; 19.11.2016