简体   繁体   English

SQLAlchemy JOIN与邻接列表

[英]SQLAlchemy JOIN vs Adjacency List

Consider the following model: 考虑以下模型:

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)

Suppose I want to access the C ids given an object A. Is this the correct (and fastest) way to do this? 假设我要访问给定对象A的C ID,这是正确的(最快的方法)吗? Or should I go for a JOIN query or other SQL magic? 还是我应该去进行JOIN查询或其他SQL魔术?

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

* EDIT * Changing C per A in the queries! *编辑*在查询中每A更改C!

You can create a simple query to solve your issue as following: 您可以创建一个简单的查询来解决您的问题,如下所示:

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

c_list will contain every object matching the join condition. c_list将包含每个符合连接条件的对象。 If you want to see the generated query, it's easy: 如果要查看生成的查询,这很简单:

print(str(q))

SELECT 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 选择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

* EDIT * This approach is more efficient than iterating over python objects as: You only have one single query that is resolved by the DB, if you iterate over your objects SQLAlchemy might need to fire some triggers to load the remaining objects from the database read loading relationships . *编辑*这种方法比遍历python对象更有效,因为:您只有一个由数据库解析的查询,如果遍历对象,SQLAlchemy可能需要触发一些触发器来从读取的数据库中加载其余对象加载关系

Next is the script I've used to replicate your case: 接下来是我用来复制案例的脚本:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM