sqlalchemy filtrar varias columnas


81

¿Cómo combino dos columnas y aplico el filtro? Por ejemplo, quiero buscar en las columnas "nombre" y "apellido" al mismo tiempo. Así es como lo he estado haciendo si buscaba solo una columna:

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

4
Pensé que esta pregunta coincidía con el problema que tengo, pero las respuestas no se aplican a mi escenario particular. Si el nombre es "joe" y el apellido es "smith", estoy buscando una declaración de filtro que coincida cuando el searchVar proporcionado es "joe smith". Es decir, los campos deben concatenarse (con espacio agregado) antes de realizar la prueba. Parece un escenario del mundo muy real.
Groovee60

1
@ Groovee60 Esto es exactamente lo que estoy buscando. Le agradecería si pudiera compartir su solución, si encuentra una.
Lilylakshi

Respuestas:


80

Hay varias formas de hacerlo:

Usando filter()( y operador)

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

Usando filter_by()( y operador)

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

Encadenamiento filter()o filter_by()( y operador)

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

El uso or_(), and_()ynot()

from sqlalchemy import and_, or_, not_

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

2
¿Existen diferencias de rendimiento notables para estos diferentes enfoques?
Miek

2
La mayoría de los diferentes enfoques terminarán generando la misma consulta, por lo que en la mayoría de los casos no verá una diferencia de rendimiento.
Asa Stallard

Estoy un poco confundido. Los filter_bydocumentos dicen que es para filtrar el argumento de palabras clave: query(Foo).filter_by(bar='baz'). ¿Cómo se relaciona eso con la sintaxis que usó en su respuesta anterior?
tel

76

Simplemente puede llamar filtervarias veces:

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

36
¿Existe alguna diferencia de rendimiento entre el uso de múltiples filter()métodos y el uso de la combinación de múltiples condiciones (por or_o and_) en una sola filter, en grandes tablas mysql?
exAres

6
¿Las filterllamadas múltiples actuarían como una lógica en ANDlugar de una OR?
Danodonovan

12
sería AND
Lyman Zerga

6
No lo creo - cuando miras str (User.filter (cond1) .filter (cond2)) genera el sql final con solo las condiciones "y" ed.
Shankar ARUL - jupyterdata.com

60

Puede usar la or_función de SQLAlchemy para buscar en más de una columna (el guión bajo es necesario para distinguirla de la de Python or).

He aquí un ejemplo:

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

7
Puede usar el |operador en lugar de or_, así (User.firstname.like(searchVar)) | (User.lastname.like(searchVar)), sin embargo, debe tener cuidado con la |precedencia, sin paréntesis puede producir resultados MUY inesperados cuando se mezcla con operadores de comparación.
Daniel Kluev

1
¿No debería serlo filter.or_( case1, case 2)?
fedorqui 'SO deja de dañar'

2
Esto está mal, ya que la pregunta es sobre ORM pero el enlace conduce a expresiones.
user2846569

1
Estaba usando múltiples declaraciones de filtro antes de lo cual aumentó la latencia dramáticamente. Lo cambié a or_ y está regresando MUCHO más rápido. Gracias @ gclj5
Jimmy

1

Un fragmento de código genérico que funcionará para varias columnas. Esto también se puede utilizar si es necesario implementar condicionalmente la funcionalidad de búsqueda en la aplicación.

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()

Nota: %%es importante omitir% formatear la consulta.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.