Diferencia entre filter y filter_by en SQLAlchemy

304

¿Alguien podría explicar la diferencia entre filtery filter_byfunciones en SQLAlchemy? ¿Cuál debería estar usando?

bodacydo
fuente

Respuestas:

393

filter_by se usa para consultas simples en los nombres de columna usando kwargs regulares, como

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

Lo mismo se puede lograr con filterno usar kwargs, sino con el operador de igualdad '==', que se ha sobrecargado en el objeto db.users.name:

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

También puede escribir consultas más potentes utilizando filter, como expresiones como:

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

Daniel Velkov
fuente
22
¿Cómo funciona esto debajo del capó? ¿No db.users.name=='Ryan'evaluaría una vez a una constante y luego no tendría sentido a partir de entonces? Parece que uno necesitaría usar una lambda para que esto funcione.
Hamish Grubijan
46
el operador de igualdad está sobrecargado
Daniel Velkov
99
type(model.column_name == 'asdf')sqlalchemy.sql.elements.BinaryExpression
Nick T
11
Tenga cuidado al usar .filter. una consulta como id=12345, query(users).filter(id == id)no se filtrará users.id. En cambio, evaluará id == idcomo Truey devolverá a todos los usuarios. .filter(users.id == id)Debe usar (como se muestra arriba). Cometí este error hoy temprano.
Nico Cernek
118

En realidad, los fusionamos originalmente, es decir, había un método similar a un "filtro" que aceptaba , *argsy **kwargsdonde podía pasar una expresión SQL o argumentos de palabras clave (o ambos). De hecho, me parece mucho más conveniente, pero la gente siempre estaba confundida, ya que generalmente todavía superan la diferencia entre column == expressiony keyword = expression. Entonces los dividimos.

zzzeek
fuente
30
Creo que su punto sobre column == expressionvs. keyword = expressiones el punto clave que debe hacerse sobre la diferencia entre filtery filter_by. ¡Gracias!
Hollister
2
Soy nuevo en sqlalchemy, así que discúlpeme si esta es una pregunta estúpida, pero filter_by () no parece permitir ni siquiera las condiciones más simples, como "precio> = 100". Entonces, ¿por qué tener filter_by () funciona de todos modos, si solo puede usarlo para la condición más simple como "precio = 100"?
PawelRoman
18
porque a la gente le gusta
zzzeek
3
¿Hay alguna diferencia de rendimiento entre ellos? Estaba pensando que filter_bypodría ser un poco más rápido que filter.
Devi
66
El punto de uso filter_byes poder escribir solo el nombre del campo, para esa clase, no se hacen preguntas, aunque flterrequiere el objeto de columna real, que generalmente requerirá que uno escriba (y lea) al menos un nombre de clase redundante. Entonces, si uno quiere filtrar por igualdad, es bastante conveniente.
jsbueno
36

filter_byutiliza argumentos de palabras clave, mientras que filterpermite argumentos de filtrado pitónico comofilter(User.name=="john")

Johannes Charra
fuente
34

Es un azúcar de sintaxis para una escritura de consulta más rápida. Su implementación en pseudocódigo:

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

Para Y puedes simplemente escribir:

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

por cierto

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

Se puede escribir como

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

También puede obtener objetos directamente por PK a través del getmétodo:

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

Cuando se usa getmayúsculas y minúsculas, es importante que el objeto se pueda devolver sin una solicitud de base de datos desde la identity mapcual se puede usar como caché (asociado con la transacción)

enomad
fuente
Estos ejemplos de código son engañosos: las clases e instancias de tabla base declarativas no tienen métodos de filtro ni de consulta; ellos usan la sesión.
tortugas son lindas
Me reproduzco users.filterde la respuesta anterior. Y puede ser mi culpa :) el queryatributo es query_property y es un azúcar bastante estándar hoy en día
enomad