Різниця між filter і filter_by в SQLAlchemy


304

Чи може хтось пояснити різницю між функціями filterта filter_byфункціями в SQLAlchemy? Яким я повинен користуватися?

Відповіді:


393

filter_by використовується для простих запитів до імен стовпців, використовуючи звичайні kwargs, наприклад

db.users.filter_by(name='Joe')

Те ж саме можна зробити і з filterвикористанням не kwargs, а замість цього оператора рівності '==', який був перевантажений об'єктом db.users.name:

db.users.filter(db.users.name=='Joe')

Ви також можете писати більш потужні запити, використовуючи filterтакі вирази, як:

db.users.filter(or_(db.users.name=='Ryan', db.users.country=='England'))


22
Як це працює під кришкою? Чи не db.users.name=='Ryan'оцінювали б один раз постійним і потім з того часу були безглуздими? Здається, що для цього потрібно використовувати лямбда.
Хаміш Грубіян

46
оператор рівності перевантажений
Даніель Велков

9
type(model.column_name == 'asdf')sqlalchemy.sql.elements.BinaryExpression
Нік Т

11
Будьте обережні при використанні .filter. запит, як-от id=12345, query(users).filter(id == id)не фільтрується users.id. Натомість він оцінить id == idяк Trueі поверне всіх користувачів. Вам потрібно скористатися .filter(users.id == id)(як описано вище). Я зробив цю помилку раніше сьогодні.
Ніко Чернек

118

Ми насправді їх спочатку об'єднали разом, тобто був метод, подібний до фільтру, який прийняв, *argsі **kwargsде можна було передавати аргументи SQL або ключові слова (або обидва). Я насправді вважаю це набагато зручнішим, але люди завжди збентежили це, оскільки вони зазвичай все ще долають різницю між column == expressionі keyword = expression. Тому ми їх розкололи.


30
Я думаю, що ваша думка про column == expressionпорівняння keyword = expressionє ключовим моментом, що має стосуватися різниці між filterта filter_by. Дякую!
Холлістер

2
Я новачок у sqlalchemy, тому вибачте мене, якщо це дурне питання, але filter_by (), здається, не дозволяє навіть дуже простих умов, таких як "ціна> = 100". Отже, навіщо функціонувати filter_by () у будь-якому випадку, якщо ви можете використовувати його лише для найпростіших умов, таких як "ціна = 100"?
PawelRoman

18
тому що людям це подобається
zzzeek

3
Чи є різниця між продуктивністю між ними? Я думав, що це filter_byможе бути трохи швидше, ніж filter.
Деві

6
Сенс використання filter_byполягає в тому, щоб мати можливість записувати назву поля для цього класу, без запитань, тоді як flterпотрібен власне об'єкт стовпця - для якого зазвичай потрібно буде набрати (і прочитати) принаймні зайве ім’я класу. Отже, якщо хочеться фільтрувати по рівності, це досить зручно.
jsbueno

36

filter_byвикористовує аргументи ключових слів, тоді як filterдозволяє пітонічні фільтруючі аргументи типуfilter(User.name=="john")


34

Це синтаксичний цукор для швидшого написання запиту. Її реалізація в псевдокоді:

def filter_by(self, **kwargs):
    return self.filter(sql.and_(**kwargs))

Для І ви можете просто написати:

session.query(db.users).filter_by(name='Joe', surname='Dodson')

btw

session.query(db.users).filter(or_(db.users.name=='Ryan', db.users.country=='England'))

можна записати як

session.query(db.users).filter((db.users.name=='Ryan') | (db.users.country=='England'))

Також ви можете отримати об'єкт безпосередньо ПК через getметод:

Users.query.get(123)
# And even by a composite PK
Users.query.get(123, 321)

При використанні getвипадку важливо, щоб об'єкт можна було повернути без запиту бази даних, з identity mapякого можна використовувати кеш (пов'язаний з транзакцією)


Ці приклади коду вводять в оману: класи декларативних базових таблиць та екземпляри не мають ні методу фільтра, ні запитів; вони використовують сеанс.
Черепахи милі

Я відтворюю users.filterз попередньої відповіді. І, можливо, я є моєю виною :) queryатрибут query_property і його цілком стандартний цукор в даний час
enomad
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.