2015-11-24 42 views
1

考慮以下模型:SQLAlchemy的JOIN VS鄰接表

class A(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    bs = db.relationship('B', backref='A') 

class B(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    cs = db.relationship('C', backref='A') 

class C(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 

假設我要訪問給定的對象A的C IDS這是正確的,最快的方式做到這一點?或者我應該去加入查詢或其他SQL魔法?

a = A.query.get(1) 
c_ids = [c.id for b in a.bs for c in b.cs] 

回答

0

*編輯*在查詢每一個改變!C

您可以創建一個簡單的查詢,以解決您的問題如下:

q = session.query(C).join(B).join(A) 
c_list = q.all() 

c_list將包含每個對象相匹配的連接條件。 如果你想看到生成的查詢,很容易:

print(str(q)) 

選擇c_table.c_id AS c_table_c_id,c_table.id AS c_table_id FROM c_table JOIN b_table ON b_table.id = c_table.c_id JOIN a_table ON a_table.id = b_table.a_id

*編輯* 這種方法比遍歷Python對象更有效,因爲:你只需要一個由DB解決一個單一的查詢,如果你伊特對您的對象進行速率SQLAlchemy可能需要觸發一些觸發器來從數據庫讀取loading relationships加載剩餘的對象。

接下來是我用過複製你的情況下,腳本:

from sqlalchemy import Column, create_engine, ForeignKey 
from sqlalchemy.orm import relationship, sessionmaker 
from sqlalchemy.types import Integer 
from sqlalchemy.ext.declarative import declarative_base 

model = declarative_base() 

class A(model): 
    __tablename__ = 'a_table' 
    id = Column(Integer, primary_key=True) 
    bs = relationship('B', backref='A') 

class B(model): 
    __tablename__ = 'b_table' 
    a_id = Column(Integer, ForeignKey('a_table.id')) 
    id = Column(Integer, primary_key=True) 
    cs = relationship('C', backref='B') 

class C(model): 
    __tablename__ = 'c_table' 
    c_id = Column(Integer, ForeignKey('b_table.id')) 
    id = Column(Integer, primary_key=True) 


engine = create_engine('postgresql+psycopg2://playground:[email protected]:5432/playground') 
session_factory = sessionmaker(bind=engine) 
session = session_factory() 

model.metadata.create_all(engine) 
a = A() 
b = B(A=a) 
c = C(B=b) 
session.add(a) 
session.commit() 

q = session.query(C).filter(C.id == 1) 
c = q.first() 
print(c.B.A.id) 

q = session.query(A).filter(A.id == 1) 
a = q.first() 
c_id = [c.id for a in a.bs for c in b.cs] 

q = session.query(C).join(B).join(A) 
c_list = q.all() 

print(str(q)) 
+0

這將選擇A IDS 「選擇a_table.id AS a_table_id」 不是C IDS。 – blueSurfer

+0

Ups!抱歉!我的錯!我糾正了錯誤。 – vamaq