web-dev-qa-db-fra.com

Utilisation de OR dans SQLAlchemy

J'ai regardé à travers la documentation et je n'arrive pas à trouver comment faire une requête OR dans SQLAlchemy. Je veux juste faire cette requête.

SELECT address FROM addressbook WHERE city='boston' AND (lastname='bulger' OR firstname='whitey')

Devrait être quelque chose comme

addr = session.query(AddressBook).filter(City == "boston").filter(????)
162
JiminyCricket

De la tutoriel :

from sqlalchemy import or_
filter(or_(User.name == 'ed', User.name == 'wendy'))
281
Bastien Léonard

SQLAlchemy surcharge les opérateurs au niveau des bits &, | et ~ donc au lieu de la syntaxe de préfixe laide et difficile à lire avec or_() et and_() (comme dans Réponse de Bastien ) vous pouvez utiliser ces opérateurs:

.filter((AddressBook.lastname == 'bulger') | (AddressBook.firstname == 'whitey'))

Notez que les parenthèses ne sont pas facultatives en raison de la priorité des opérateurs au niveau du bit.

Donc, toute votre requête pourrait ressembler à ceci:

addr = session.query(AddressBook) \
    .filter(AddressBook.city == "boston") \
    .filter((AddressBook.lastname == 'bulger') | (AddressBook.firstname == 'whitey'))
286
ThiefMaster

l'opérateur or_ peut être utile en cas de nombre inconnu de composants de requête OR.

Par exemple, supposons que nous créons un service REST avec peu de filtres facultatifs, qui devrait renvoyer un enregistrement si l'un des filtres renvoie la valeur true. D'un autre côté, si le paramètre n'était pas défini dans une requête, notre requête ne devrait pas changer. Sans or_ function, nous devons faire quelque chose comme ceci:

query = Book.query
if filter.title and filter.author:
    query = query.filter((Book.title.ilike(filter.title))|(Book.author.ilike(filter.author)))
else if filter.title:
    query = query.filter(Book.title.ilike(filter.title))
else if filter.author:
    query = query.filter(Book.author.ilike(filter.author))

Avec or_ function, il peut être réécrit pour:

query = Book.query
not_null_filters = []
if filter.title:
    not_null_filters.append(Book.title.ilike(filter.title))
if filter.author:
    not_null_filters.append(Book.author.ilike(filter.author))

if len(not_null_filters) > 0:
    query = query.filter(or_(*not_null_filters))
29
Valar

Cela a été vraiment utile. Voici mon implémentation pour toute table donnée:

def sql_replace(self, tableobject, dictargs):

    #missing check of table object is valid
    primarykeys = [key.name for key in inspect(tableobject).primary_key]

    filterargs = []
    for primkeys in primarykeys:
        if dictargs[primkeys] is not None:
            filterargs.append(getattr(db.RT_eqmtvsdata, primkeys) == dictargs[primkeys])
        else:
            return

    query = select([db.RT_eqmtvsdata]).where(and_(*filterargs))

    if self.r_ExecuteAndErrorChk2(query)[primarykeys[0]] is not None:
        # update
        filter = and_(*filterargs)
        query = tableobject.__table__.update().values(dictargs).where(filter)
        return self.w_ExecuteAndErrorChk2(query)

    else:
        query = tableobject.__table__.insert().values(dictargs)
        return self.w_ExecuteAndErrorChk2(query)

# example usage
inrow = {'eqmtvs_id': eqmtvsid, 'datetime': dtime, 'param_id': paramid}

self.sql_replace(tableobject=db.RT_eqmtvsdata, dictargs=inrow)
3
delpozov