Разница между 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))

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

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

кстати

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метода PK :

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.