sqlalchemy фільтрує кілька стовпців


82

Як об’єднати два стовпці та застосувати фільтр? Наприклад, я хочу одночасно шукати як у стовпцях «ім’я», так і «прізвище». Ось як я це робив, шукаючи лише один стовпець:

query = meta.Session.query(User).filter(User.firstname.like(searchVar))

4
Я вважав, що це питання відповідає моєму питанню, але відповіді не стосуються мого конкретного сценарію. Якщо ім'я "joe", а прізвище "smith", я шукаю оператор фільтра, який буде відповідати, коли наданий searchVar буде "joe smith". Тобто, поля потрібно об’єднати (з додаванням місця) перед проведенням тесту. Здається, це справжній сценарій.
Groovee60

1
@ Groovee60 Це саме те, що я шукаю. Буду вдячний, якщо ви зможете поділитися своїм рішенням, якщо знайдете його.
Lilylakshi

Відповіді:


84

Є кілька способів це зробити:

Використання filter()( та оператора)

query = meta.Session.query(User).filter(
    User.firstname.like(search_var1),
    User.lastname.like(search_var2)
    )

Використання filter_by()( та оператора)

query = meta.Session.query(User).filter_by(
    firstname.like(search_var1),
    lastname.like(search_var2)
    )

Мережа filter()або filter_by()( і оператор)

query = meta.Session.query(User).\
    filter_by(firstname.like(search_var1)).\
    filter_by(lastname.like(search_var2))

Використовуючи or_(), and_()іnot()

from sqlalchemy import and_, or_, not_

query = meta.Session.query(User).filter(
    and_(
        User.firstname.like(search_var1),
        User.lastname.like(search_var2)
    )
)

2
Чи існують якісь помітні відмінності в ефективності для цих різних підходів?
Miek,

2
Більшість різних підходів в кінцевому підсумку генерують однакові запити, тому в більшості випадків ви не побачите різниці в продуктивності.
Asa Stallard

Я трохи розгублений. У filter_byдокументах кажуть , що це для фільтрації за ключовим словом аргументу: query(Foo).filter_by(bar='baz'). Як це пов’язано із синтаксисом, який ви використали у вашій відповіді вище?
тел

76

Ви можете просто зателефонувати filterкілька разів:

query = meta.Session.query(User).filter(User.firstname.like(searchVar1)). \
                                 filter(User.lastname.like(searchVar2))

36
чи є різниця у продуктивності між використанням декількох filter()методів та використанням комбінації декількох умов (by or_або and_) в одному filter, на великих таблицях mysql?
exAres

6
Чи будуть кілька filterвикликів діяти як логічні, ANDа не як OR?
данодонован

6
Я не думаю, що так - коли ви дивитесь на str (User.filter (cond1) .filter (cond2)), генерується кінцевий sql лише з умовами "та" ed.
Шанкар АРУЛ

60

Ви можете використовувати or_функцію SQLAlchemy для пошуку в більш ніж одному стовпці (підкреслення необхідне, щоб відрізнити його від власного Python or).

Ось приклад:

from sqlalchemy import or_
query = meta.Session.query(User).filter(or_(User.firstname.like(searchVar),
                                            User.lastname.like(searchVar)))

7
Ви можете використовувати |оператор замість or_, як цей - (User.firstname.like(searchVar)) | (User.lastname.like(searchVar)), однак слід бути обережним з |пріоритетом, без дужок він може дати ДУЖЕ несподівані результати при змішуванні з операторами порівняння.
Даніель Клюєв,

1
Чи не повинно бути filter.or_( case1, case 2)?
Fedorqui 'SO prestani шкодити'

2
Це неправильно, оскільки питання стосується ORM, але посилання веде до виразів.
користувач2846569

1
Я використовував декілька операторів фільтра, перед якими різко збільшилась затримка. Я змінив його на or_, і він повертається НАБАГАТО швидше. Дякую @ gclj5
Джиммі

2

Загальний фрагмент коду, який буде працювати для декількох стовпців. Це також можна використовувати, якщо є необхідність умовно реалізувати функціональність пошуку в додатку.

search_key = "abc"
search_args = [col.ilike('%%%s%%' % search_key) for col in ['col1', 'col2', 'col3']]
query = Query(table).filter(or_(*search_args))
session.execute(query).fetchall()

Примітка: %%важливо пропустити% форматування запиту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.