0

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 ?

0 Answers0