You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ecto中分组查询时预加载关联及选择指定列的实现疑问

问题解答

1. 预加载SaleProduct关联的Product

直接在preload里用嵌套预加载语法,把:product作为sale_products的子预加载项就行。修改后的查询代码如下:

query =
  from s in Sale,
    inner_join: sp in SaleProduct,
    on: sp.sale_id == s.id,
    inner_join: p in Product,
    on: p.id == sp.product_id,
    group_by: s.id,
    order_by: [asc: :date],
    preload: [sale_products: :product]

这样返回的SaleProduct结构体里的:product字段会被正确加载,不会再出现#Ecto.Association.NotLoaded的状态。

2. 从SaleProduct中选择特定列

如果只需要SaleProduct的部分字段,可以通过自定义预加载查询实现,只筛选你需要的字段(比如quantity、product_id),避免多余字段或未加载关联导致Poison编码失败。示例代码:

# 先定义SaleProduct的筛选查询,只保留需要的字段
sp_query = from sp in SaleProduct, select: %{quantity: sp.quantity, product_id: sp.product_id}

# 主查询中使用这个自定义预加载
query =
  from s in Sale,
    inner_join: sp in SaleProduct,
    on: sp.sale_id == s.id,
    inner_join: p in Product,
    on: p.id == sp.product_id,
    group_by: s.id,
    order_by: [asc: :date],
    preload: [sale_products: {sp_query, :product}]

如果不需要预加载product,可以去掉:product,直接写preload: [sale_products: sp_query]。这样返回的sale_products列表只会包含你指定的字段,转JSON时就不会出现未加载关联的编码问题。

另外,如果你希望返回的是SaleProduct结构体而非map,可以用select: struct(sp, [:quantity, :product_id])替代上面的map写法:

sp_query = from sp in SaleProduct, select: struct(sp, [:quantity, :product_id])

内容的提问来源于stack exchange,提问作者Basil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 11:35:13