[英]SQLAlchemy secondary relationship not using JOIN
我在 SQLAlchemy 上創建了多對多關系,但由於某種原因,當我訪問它時,它不會發出 JOIN 子句,而是從三個表的叉積中選擇並使用WHERE
子句進行過濾。 我不明白為什么會這樣,以及如何解決它。
這是關聯表和主模型的 python 代碼。 輔助模型過於復雜,我認為它具有sku
和account_id
列的事實,這些列具有索引(並且一起是 PK 的一部分),這足以繼續進行
product_info_to_product_profile_association_table = Table(
"tpl_products_to_product_profiles_r1",
metadata,
sa.Column(
"sku",
sa.String(128),
# This FK is failing at the MySQL level
# sa.ForeignKey(ProductInfo.sku),
nullable=False,
),
sa.Column(
"account_id", mysql.INTEGER(11), sa.ForeignKey(ProductInfo.account_id), nullable=False
),
sa.Column(
"product_profile_id",
mysql.INTEGER(11, unsigned=True),
sa.ForeignKey("tpl_product_profiles.id"),
nullable=False,
),
sa.UniqueConstraint("sku", "account_id", "product_profile_id", name="product_unique"),
)
class ProductProfile(BillingBaseModel):
__tablename__ = "tpl_product_profiles"
id = sa.Column(mysql.INTEGER(11, unsigned=True), primary_key=True)
name = sa.Column(sa.String(90), nullable=False)
account_id = sa.Column(mysql.INTEGER(11), sa.ForeignKey(Account.id), nullable=False)
product_infos = orm.relationship(
ProductInfo,
secondary=product_info_to_product_profile_association_table,
secondaryjoin=sa.and_(
ProductInfo.sku
== orm.foreign(product_info_to_product_profile_association_table.c.sku),
ProductInfo.account_id
== orm.foreign(product_info_to_product_profile_association_table.c.account_id),
),
secondaryjoin=(
id
== orm.foreign(product_info_to_product_profile_association_table.c.product_profile_id)
),
backref=orm.backref("product_profile", uselist=False),
)
這是我嘗試通過實例訪問關系時生成的 SQL
>>> pp.product_infos
[SELECT product_info.sku..........
FROM product_info, tpl_products_to_product_profiles_r1
WHERE tpl_products_to_product_profiles_r1.product_profile_id = %s AND product_info.sku = tpl_products_to_product_profiles_r1.sku AND product_info.account_id = tpl_products_to_product_profiles_r1.account_id]
[parameters: (6L,)]
這可能不是最好的答案,但我已經深入研究了 sqlalchemy 的一些內部工作,它在執行延遲加載時顯式創建了交叉連接
if self.parent_property.secondary is not None:
q.add_criteria(
lambda q: q.select_from(
self.mapper, self.parent_property.secondary
)
)
我發現的最佳解決方案是使用某種急切加載。
不管那是
lazy='selectin'
selectinload(ProductProfile.product_infos)
並知道您將需要訪問該屬性contains_eager(ProductProfile.product_infos)
對於前兩種情況,sqlalchemy 建議您在處理x-to-many
表時使用selectin
或subquery
預加載(尤其是當 many 表很大時): https://docs.sqlalchemy.org/en/14/orm/loading_relationships。 html#what-kind-of-loading-to-use
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.