SQLAlchemy 外键映射到 id 列表,而不是实体
SQLAlchemy foreign keys mapped to list of ids, not entities
在通常的 Customer
和 Order
示例中,这种 SQLAlchemy 代码...
data = db.query(Customer)\
.join(Order, Customer.id == Order.cst_id)\
.filter(Order.amount>1000)
...将提供与例如关联的 Customer 模型的实例。大订单 (amount > 1000
)。生成的 Customer 实例还将包含他们的订单列表,因为在这个例子中我们使用 backref
是出于这个原因:
class Order:
...
customer = relationship("customers", backref=backref('orders'))
这个问题是,遍历 Customer.orders
意味着数据库将 return 完整的 Order 实例 - 基本上对 Order 的所有列执行 'select *'。
如果出于性能原因,有人想要,例如只从 Order 中读取 1 个字段(例如 id)并让 Customer 实例中的 .orders
字段成为一个简单的 ID 列表?
customers = db.query(Customer)....
...
pdb> print customers[0].orders
[2,4,7]
SQLAlchemy 可以吗?
您可以这样查询:
(
session.query(Customer.id, Order.id)
.select_from(Customer)
.join(Customer.order)
.filter(Order.amount > 1000)
)
它不会产生您所要求的确切结果,但它会为您提供一个看起来像 [(customer_id, order_id), ...]
.
的元组列表
我不完全确定你是否可以急切地将 order_ids
加载到 Customer
对象中,但我认为应该可以,如果有帮助,你可能想看看 joinedload, subqueryload and perhaps go through the relationship-loading docs。
在这种情况下,您可以将其写为;
(
session.query(Customer)
.select_from(Customer)
.join(Customer.order)
.options(db.joinedload(Customer.orders))
.filter(Order.amount > 1000)
)
并使用 noload 来避免加载其他列。
我最终以最佳方式完成了这项工作 - 使用数组聚合:
data = db.query(Customer).with_entities(
Customer,
func.ARRAY_AGG(
Order.id,
type_=ARRAY(Integer, as_tuple=True)).label('order_ids')
).outerjoin(
Orders, Customer.id == Order.cst_id
).group_by(
Customer.id
)
(CustomerEntity, list) 的 returns 元组 - 这正是我想要的。
在通常的 Customer
和 Order
示例中,这种 SQLAlchemy 代码...
data = db.query(Customer)\
.join(Order, Customer.id == Order.cst_id)\
.filter(Order.amount>1000)
...将提供与例如关联的 Customer 模型的实例。大订单 (amount > 1000
)。生成的 Customer 实例还将包含他们的订单列表,因为在这个例子中我们使用 backref
是出于这个原因:
class Order:
...
customer = relationship("customers", backref=backref('orders'))
这个问题是,遍历 Customer.orders
意味着数据库将 return 完整的 Order 实例 - 基本上对 Order 的所有列执行 'select *'。
如果出于性能原因,有人想要,例如只从 Order 中读取 1 个字段(例如 id)并让 Customer 实例中的 .orders
字段成为一个简单的 ID 列表?
customers = db.query(Customer)....
...
pdb> print customers[0].orders
[2,4,7]
SQLAlchemy 可以吗?
您可以这样查询:
(
session.query(Customer.id, Order.id)
.select_from(Customer)
.join(Customer.order)
.filter(Order.amount > 1000)
)
它不会产生您所要求的确切结果,但它会为您提供一个看起来像 [(customer_id, order_id), ...]
.
我不完全确定你是否可以急切地将 order_ids
加载到 Customer
对象中,但我认为应该可以,如果有帮助,你可能想看看 joinedload, subqueryload and perhaps go through the relationship-loading docs。
在这种情况下,您可以将其写为;
(
session.query(Customer)
.select_from(Customer)
.join(Customer.order)
.options(db.joinedload(Customer.orders))
.filter(Order.amount > 1000)
)
并使用 noload 来避免加载其他列。
我最终以最佳方式完成了这项工作 - 使用数组聚合:
data = db.query(Customer).with_entities(
Customer,
func.ARRAY_AGG(
Order.id,
type_=ARRAY(Integer, as_tuple=True)).label('order_ids')
).outerjoin(
Orders, Customer.id == Order.cst_id
).group_by(
Customer.id
)
(CustomerEntity, list) 的 returns 元组 - 这正是我想要的。