diesel version = "2.0.0"
Database Postgres
I have products and categories with many-to-many relation
Schema:
diesel::table! {
categories (id) {
id -> Int4,
name -> Varchar,
}
}
diesel::table! {
products (id) {
id -> Int4,
name -> Varchar,
description -> Varchar,
}
}
diesel::table! {
productscategories (id) {
id -> Int4,
product_id -> Int4,
category_id -> Int4,
}
}
diesel::joinable!(productscategories -> categories (category_id));
diesel::joinable!(productscategories -> products (product_id));
diesel::allow_tables_to_appear_in_same_query!(
categories,
products,
productscategories,
);
Models:
#[derive(Identifiable, Deserialize, Serialize, Debug, Queryable, AsChangeset, Clone)]
#[diesel(table_name = products)]
pub struct Product {
pub id: i32,
pub name: String,
pub description: String,
}
#[derive(Identifiable, Deserialize, Serialize, Debug, Queryable, AsChangeset, Clone)]
#[diesel(table_name = categories)]
pub struct Category {
pub id: i32,
pub name: String,
}
#[derive(Identifiable, Deserialize, Serialize, Debug, Queryable, AsChangeset, Associations)]
#[belongs_to(Product)]
#[belongs_to(Category)]
#[diesel(table_name = productscategories)]
pub struct ProductCategory {
pub id: i32,
pub product_id: i32,
pub category_id: i32,
}
To get one product with it's relation is relatively easy as mentioned Here
But how to get all products with their relative categories to have result of Vec<ProductOutDto>
:
#[derive(Deserialize, Serialize, Debug)]
pub struct ProductOutDto {
pub id: i32,
pub name: String,
pub description: String,
pub categories: Vec<Category>,
}
and possibly the other way around Vec<CategoryOutDto>
#[derive(Deserialize, Serialize, Debug)]
pub struct CategoryOutDto{
pub id: i32,
pub name: String,
pub products: Vec<Product>,
}
Currently I am getting things like :
use crate::schema::categories::dsl::categories as DbCategories;
use crate::schema::products::dsl::products as DbProducts;
use crate::schema::productscategories::dsl::productscategories as DbProductsCategories;
let query_result: Vec<(Product, Category)> = DbProducts
.inner_join(DbProductsCategories.inner_join(DbCategories))
.select((DbProducts::all_columns(), DbCategories::all_columns()))
.load::<(Product, Category)>(&mut connection)?;
then I am iterating over query_result to get transform Vec<(Product, Category)>
into Vec<ProductOutDto>
to group categories with their relative product.
the question that is there a better or standard way to achieve this without iterating my self and make such transformation ?