SQLalchemy: уточнение и создание цепочки подзапроса с помощью Union - PullRequest
0 голосов
/ 19 марта 2020

Я хотел бы построить запрос с помощью sqlalchemy, используя расширение ORM. Подумайте об этом:

class Foo(Base):
    __table__ = 'foo_table'
    id = Column(Integer)
    name = Column(String)
    prop = Column(Integer)

Теперь я хотел бы написать общую функцию, которая может возвращать мне все Foo, где имя совпадает с какой-либо строкой или где реквизит является некоторым числом:

from sqlalchemy.orm import Query
def match_name(_name):
    return Query(Foo).filter_by(name = _name)

def match_prop(_prop):
    return Query(Foo).filter_by(prop = _prop)

Каждая функция должна иметь возможность возвращать мне запрос, который я могу использовать для извлечения объектов ORM. Теперь, учитывая, что меня интересуют только идентификатор и имя этих объектов, но без изменения функций я могу действовать следующим образом:

myname = 'foo'
sqry1 = match_name(myname).subquery()
all_name_eq_foo = session.query(sqry1.c.id, sqry1.c.name).all()

myprop = 42
sqry2 = match_prop(myprop).subquery()
all_name_eq_foo = session.query(sqry2.c.id, sqry2.c.name).all()

Итак, теперь, как этого добиться за один go, в то время как использование надмножества результатов в каждом подзапросе, то есть где имя соответствует ИЛИ проп соответствует без без цепочки условий фильтра (подзапросы в этом примере просто упрощены, но могут быть более сложными для использования). Для меня это означает использование Union , что-то вроде этого:

def match_name_prop(_name, _prop):
    return Query.union([match_name(_name).subquery(), match_prop(_prop).subquery()])

с возможностью позже ограничить результирующие столбцы:

sqry3 = match_name_prop(myname, myprop).subquery()
all_name_eq_foo = session.query(sqry3.c.id, sqry3.c.name).all()

Но я не могу получить это работает. Кто-нибудь может помочь, пожалуйста?!

1 Ответ

0 голосов
/ 20 марта 2020

После нескольких часов попыток, я думаю, я нашел адекватное решение:

def match_name_prop(_name, _prop):
    return match_name(_name).union(match_prop(_prop))

, которое само по себе будет возвращать ORM-сущности, например, так:

matches = match_name_prop(myname, myprop)
matches.with_session(session).all()
#>>> [<Foo object at 0xFFFFFF>]

и затем выбрав желаемое столбцы внутри этой сущности, например:

session.query(Foo.id, Foo.name).select_entity_from(matches.subquery()).all()
#>>> [(42,'foo',)]
...