2014-11-05 28 views
0
from sqlalchemy.orm import subqueryload, joinedload, eagerload 
from sqlalchemy import Column, DateTime, String, Integer, ForeignKey, func,Float, sql 
from sqlalchemy.orm import relation 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy import create_engine 

engine = create_engine('sqlite:///testdb.sqlite') 
engine.echo = True 
Base = declarative_base() 
session = sessionmaker() 
session.configure(bind=engine) 
Base.metadata.create_all(engine) 
s= session() 

class Stock(Base): 
__tablename__ = 'stock' 
stock_id = Column(Integer, primary_key=True) 
name = Column(String) 
prices = relation("StockPrice") 

class StockPrice(Base): 
__tablename__ = 'stock_price' 
stock_id = Column(Integer, ForeignKey('stock.stock_id'), primary_key=True) 
date = Column(String, primary_key=True) 
price = Column(Float) 
source = Column(String, primary_key=True) 
user = Column(String) 

Base.metadata.create_all(engine) 

stockprice1 = StockPrice(stock_id = 1, date="2014-10-29", price="170.0", source="X Firm", user="U1") 
stockprice2 = StockPrice(stock_id = 1, date="2014-10-30", price="175.0", source="X Firm", user="U2") 
stock1 = Stock(stock_id = 1, name = "GOOGLE", prices=[stockprice1, stockprice2]) 

stockprice1 = StockPrice(stock_id = 2, date="2014-10-29", price="150.0", source="X Firm", user="U1") 
stockprice2 = StockPrice(stock_id = 2, date="2014-10-30", price="155.0", source="X Firm", user="U2") 
stock2 = Stock(stock_id = 2, name = "YAHOO", prices=[stockprice1, stockprice2]) 

s.add_all([stock1, stock2]) 
s.commit() 

的價格爲股票的預先加載:熱切負載價格的股票給定日期加入一個條件在SQLAlchemy的ORM熱切負載

stock = s.query(Stock).options(joinedload(Stock.prices)).filter(Stock.stock_id == 1).one()

方式一:

stock = s.query(Stock).options(joinedload(Stock.prices)).filter(Stock.stock_id == 1).filter(StockPrice.date == "2014-10-30").one()

但是,這種方法的問題是,如果你有像StockPrice可能的表相關的股票,如果你想加載第e給定日期的所有關係,那麼在加入所有關係後結果集變得非常龐大。過濾器在WHERE子句中添加條件,相反,我需要一種方式來指定加入時加載的條件。

stock = s.query(Stock).options(joinedload(Stock.prices, #condition does not work here)).filter(Stock.stock_id == 1).one()

回答

4

代替joinedload(Stock.prices)做到以下幾點:

stock = (s.query(Stock) 

     # @note: this replaces `joinedload(Stock.prices)` 
     .join(StockPrice, 
       and_(StockPrice.stock_id == Stock.stock_id, 
        StockPrice.date == "2014-10-30") 
       ) 

     # effectively *trick* SQLAlchemy into thinking that above we loaded all 
     # items for the relationship *Stock.prices* 
     .options(contains_eager(Stock.prices)) 

     ).get(1) # will retrieve the instance for Stock.stock_id = 1 
+0

的偉大工程。謝謝。 – dumper 2014-11-06 12:57:38