2015-11-24 27 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