gpt4 book ai didi

python - sqlalchemy 关系 primaryjoin 与自身和父列

转载 作者:太空宇宙 更新时间:2023-11-04 02:35:12 30 4
gpt4 key购买 nike

如果我有模型:

class A(Base):
a_id = Column(Integer, primary_key=True)
other = Column(Text)
name = Column(Text)


class B(Base):
b_id = Column(Integer, primary_key=True)
other = Column(Text)


class C(Base):
c_id = Column(Integer, primary_key=True)
b_id = Column(ForeignKey(B.b_id))
b = relationship(B)
name = Column(Text)

a = relationship(
A,
primaryjoin=and_(
A.name == foreign(name),
A.other == foreign(B.other)))

如何获取关系C.a工作这样 session.query(C).options(joinedload(C.a))不会失败。

在普通 SQL 中我会这样做:

select * from c 
join b using(b_id)
join a on a.name = c.name and a.other = b.other

a.name, a.other 有唯一约束,所以我知道我会得到 1 或 0 a根据 c .

我想我需要使用 secondary=在某种程度上,但我能找到的所有示例都是纯粹的多对多示例。

谢谢!

最佳答案

您必须使用 relationship to a non primary mapper 而不是次级,因为:

There is one complex join case where even this technique (composite "secondary" join) is not sufficient; when we seek to join from A to B, making use of any number of C, D, etc. in between, however there are also join conditions between A and B directly. In this case, the join from A to B may be difficult to express with just a complex primaryjoin condition, as the intermediary tables may need special handling, and it is also not expressable with a secondary object, since the A->secondary->B pattern does not support any references between A and B directly.

因此,按照文档中的示例,我们可以使用 non primary mapper 建立您的关系。将类 A 映射到表 ab 之间的连接:

from sqlalchemy import create_engine, Column, Integer, Text, ForeignKey, join, and_
from sqlalchemy.orm import relationship, mapper, sessionmaker, foreign
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///', echo=True)
Base = declarative_base()
Base.metadata.bind = engine
Session = sessionmaker()

class A(Base):
__tablename__ = 'a'
a_id = Column(Integer, primary_key=True)
other = Column(Text)
name = Column(Text)


class B(Base):
__tablename__ = 'b'
b_id = Column(Integer, primary_key=True)
other = Column(Text)

j = join(A, B, A.other == B.other)
A_viab = mapper(A, j, non_primary=True, properties={
"other": [j.c.a_other, j.c.b_other]
})


class C(Base):
__tablename__ = 'c'
c_id = Column(Integer, primary_key=True)
b_id = Column(ForeignKey(B.b_id))
b = relationship(B)
name = Column(Text)

a = relationship(
A_viab,
primaryjoin=and_(foreign(name) == A_viab.c.name,
b_id == A_viab.c.b_id))

并在行动中:

In [4]: session.add(A(name='name', other='other'))

In [5]: session.add(C(name='name', b=B(other='other')))

In [6]: session.commit()
...

In [7]: c = session.query(C).options(joinedload(C.a)).first()
2018-01-04 15:10:21,338 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2018-01-04 15:10:21,340 INFO sqlalchemy.engine.base.Engine SELECT c.c_id AS c_c_id, c.b_id AS c_b_id, c.name AS c_name, a_1.other AS a_1_other, b_1.other AS b_1_other, a_1.a_id AS a_1_a_id, a_1.name AS a_1_name, b_1.b_id AS b_1_b_id
FROM c LEFT OUTER JOIN (a AS a_1 JOIN b AS b_1 ON a_1.other = b_1.other) ON c.name = a_1.name AND c.b_id = b_1.b_id
LIMIT ? OFFSET ?
2018-01-04 15:10:21,340 INFO sqlalchemy.engine.base.Engine (1, 0)

In [8]: c.a
Out[8]: <cplxjoin.A at 0x7f0c81599630>

生成的查询与您的手动 SQL 不完全相同,但 afaic 应该是等效的。

关于python - sqlalchemy 关系 primaryjoin 与自身和父列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48080591/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com