2014-04-25 3 views
0

Essentiellement, j'ai une question de SQLAlchemy qui ressemble à ceci:Quelle est la manière la plus idiomatique d'exprimer cette requête avec SQAlchemy?

foos = Foo.query.filter(Foo.expiration < cutoff) 
valid_foos = [] 
for foo in foos: 
    last_bar = foo.bars.order_by('created_at desc').first() 
    if last_bar.state != 'fatal': 
     valid_foos.append(foo) 

Le but étant de sélectionner tous les foos pour lesquels l'état de la première barre qui s'y rapporte est pas « fatale ». Il semble que les sous-requêtes pourraient aider ici. Cependant, j'ai du mal à comprendre comment je peux exprimer last_bar = foo.bars.order_by('created_at desc').first() de cette façon.

Répondre

0

Je pense que la façon la plus simple et le plus polyvalent de le faire est d'utiliser l'extension Hybrid Attributes. Lorsque vous vous étendez modelez comme ci-dessous:

class Foo(Base): 
    __tablename__ = "foo" 
    # ... 

    @hybrid_property 
    def last_bar_state(self): 
     _last_bar = self.bars.order_by(Bar.created_at.desc()).first() 
     return _last_bar.state 

    @last_bar_state.expression 
    def _last_bar_state_expression(cls): 
     q = (select([Bar.state.label("state")]) 
       .where(Bar.foo_id == cls.foo_id) 
       .order_by(Bar.created_at.desc()) 
       .limit(1) 
       ).label("last_bar_state_sub") 
     return q 

vous serez en mesure d'utiliser last_bar_state aussi bien en mémoire, ainsi que dans la requête:

foos = session.query(Foo).filter(Foo.expiration < cutoff) 
foos = foos.filter(Foo.last_bar_state != 'fatal').all() 
0

Utilisez un sous-requête pour trouver la dernière barre pour chaque Foo. Ensuite, utilisez cela pour rejoindre et filtrer Bar lorsque vous interrogez Foo. Ceci ne sélectionnera pas Foo si elle n'a pas de barre, vous pouvez utiliser une jointure externe à la place pour cela.

Questions connexes