I have 3 tables: sales
, products
, and sales_products
. Sales contains information about sales made as the name implies, products contains information about various products, and sales_products is an intermediary table with a sale_id
product_id
composite key, and a quantity field.
My current Ecto query looks like this:
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]
This works in that I get a result similar to:
[%Sale{
[...],
sale_id: ID,
sale_products: [
%SaleProduct { product: #Ecto.Association.NotLoaded<association :product is not loaded>, sale_id: ID, product_id: PID }
],
[...]
}]
Firstly, how do I preload 'product' for SaleProduct when it is inside its own preloaded struct?
And secondly, and the main question, how do I select only specific columns from sale_products
? I am trying to return this as a json
Object, however I get a Poison error as it does not know how to encode some fields, and I just want to select the fields I need from the SaleProduct struct to rectify this.
CodePudding user response:
I solved this.
To preload product for SaleProduct, you just nest the preload:
preload: [..., saleproducts: [:product], ...]
And to solve the overarching question, you actually don't use preload at all, but rather fragment
:
select: %{products: fragment("JSON_ARRAYAGG(JSON_OBJECT('product_id', ?, 'quantity', ?))", sp.product_id, sp.quantity)}