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
相关产品推荐
相关产品推荐

