[英]SQLAlchemy JOIN vs Adjacency List
考慮以下模型:
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 ID,這是正確的(最快的方法)嗎? 還是我應該去進行JOIN查詢或其他SQL魔術?
a = A.query.get(1)
c_ids = [c.id for b in a.bs for c in b.cs]
*編輯*在查詢中每A更改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對象更有效,因為:您只有一個由數據庫解析的查詢,如果遍歷對象,SQLAlchemy可能需要觸發一些觸發器來從讀取的數據庫中加載其余對象加載關系 。
接下來是我用來復制案例的腳本:
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:playground@localhost: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))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.