2014-03-05 25 views
2

假设我有2个类:Foo和Bar。假设一个Foo可以有很多条(通过foo.Bars)。小节有一个end_date来指示小节何时结束。尚未结束的钢筋默认设置为'9999-12-31'。即使他们有不同的过滤器,两个sqlalchemy查询返回相同的结果

我在下面写了两个查询来获得Foo,但使用了不同的条形过滤器,这样第一个查询就给了我没有结束的条形图;第二个给我吧,已经结束。

today = date.today().strftime("%Y-%m-%d") 

    current = session.query(Foo)\ 
         .join(Bar)\ 
         .filter(
          and_(
           Foo.code=='MY_STRING', 
           Bar.end_date >= today, 
           ) 
         )\ 
         .options(contains_eager('Bars'))\ 
         .one() 

    previous = session.query(Foo)\ 
         .join(Bar)\ 
         .filter(
          and_(
           Foo.code=='MY_STRING', 
           Bar.end_date < today, 
           ) 
         )\ 
         .options(contains_eager('Bars'))\ 
         .one() 

出于某种原因previous.Bars是即使我们过滤棒是不同一样current.Bars(那是我尝试至少)。例如。 current.Bars返回[bar1, bar2, bar3]previous.Bars返回[bar1, bar2, bar3]

如果我转了两个查询(即把previouscurrent之前),那么当前的酒吧一样previous.Bars。例如。 current.Bars返回[bar4, bar5, bar6]previous.Bars返回[bar4, bar5, bar6]

请注意,我100%确定previous.Bars中的基础数据应该与current.Bars不同。即我应该得到[bar4, bar5, bar6]previous.Bars[bar1, bar2, bar3]current.Bars

有人请解释为什么我得到了相同的结果?我该如何解决这个问题?我意识到,只有一个查询可能会更好。

在此先感谢!

PS我使用的是0.8版本

+0

什么版本的SQLAlchemy您使用的是:因为你需要双方反正,只是做在Python端轻松这种分离? – Drewness

+0

@Drewness我正在使用0.8版本 – ksindi

回答

2

问题行是.options(contains_eager('Bars'))。它基本上告诉sqlachemy该查询包含所有Bars加载的每个foo。因此,当您访问foo.Bars时,它不再查询数据库,因为它已将join中的那些(已过滤的)条视为并假定它们是完整的foo.Bars关系。
下次运行查询时,sqlalchemy意识到对象Foo已被加载(包括其关系Bars),并基本返回当前在会话(内存)中的内容。

您可以通过使用session.expunge(current)previous执行查询之前,让sqlalchemy将完全重新加载它从会话中删除的对象的工作,解决这个问题,但你之后使用current例如要小心,因为它不是会议的一部分了。

更好尚未

today = datetime.datetime.today()#.strftime("%Y-%m-%d") 
foo = (session.query(Foo) 
     .options(joinedload(Foo.Bars)) 
     .filter(Foo.code=='MY_STRING') 
     .one() 
     ) 
prev_bars = [bar for bar in foo.Bars if bar.end_date < today] 
curr_bars = [bar for bar in foo.Bars if bar.end_date >=today] 
print foo 
print prev_bars 
print curr_bars 
相关问题