Replies: 5 comments 2 replies
-
Played a little bit more with this technique and now i don't even need to remember all prefixes myself :) My prefixeruse sea_orm::prelude::*;
use sea_orm::sea_query::{Alias, IntoIden, SelectExpr, SelectStatement};
use sea_orm::{EntityTrait, QueryTrait};
pub struct Prefixer<S: QueryTrait<QueryStatement = SelectStatement>> {
pub selector: S,
}
impl<S: QueryTrait<QueryStatement = SelectStatement>> Prefixer<S> {
pub fn new(selector: S) -> Self {
Self { selector }
}
pub fn add_columns<T: EntityTrait>(mut self, entity: T) -> Self {
for col in <T::Column as sea_orm::entity::Iterable>::iter() {
let alias = format!("{}{}", entity.table_name(), col.to_string()); // we use entity.table_name() as prefix
self.selector.query().expr(SelectExpr {
expr: col.select_as(col.into_expr()),
alias: Some(Alias::new(&alias).into_iden()),
window: None,
});
}
self
}
} And this is how i use it: let select = account::Entity::find()
.filter(account::Column::UserId.eq(user.id))
.order_by_asc(account::Column::CreatedAt)
.select_only();
let result = Prefixer::new(select)
.add_columns(account::Entity) // This is what changed
.add_columns(flat::Entity) // This is what changed
.add_columns(house::Entity) // This is what changed
.selector
.join(JoinType::LeftJoin, account::Relation::Flat.def())
.join(JoinType::LeftJoin, flat::Relation::House.def())
.into_model::<Response>()
.all(&db)
.await?; #[derive(Debug, Serialize)]
pub struct Response {
pub account: SafeAccount,
pub flat: flat::Model,
pub house: house::Model,
}
impl FromQueryResult for Response {
fn from_query_result(res: &sea_orm::QueryResult, _pre: &str) -> Result<Self, sea_orm::DbErr> {
let account = account::Model::from_query_result(res, account::Entity.table_name())?.into();
let flat = flat::Model::from_query_result(res, flat::Entity.table_name())?;
let house = house::Model::from_query_result(res, house::Entity.table_name())?;
Ok(Self {
account,
flat,
house,
})
}
} |
Beta Was this translation helpful? Give feedback.
-
More abstractions to the god of abstractions: use sea_orm::{EntityTrait, FromQueryResult};
pub fn parse_query_to_model<M: FromQueryResult, E: EntityTrait>(
res: &sea_orm::QueryResult,
) -> Result<M, sea_orm::DbErr> {
M::from_query_result(res, E::default().table_name())
} impl FromQueryResult for AccountUnwindSafe {
fn from_query_result(res: &sea_orm::QueryResult, _pre: &str) -> Result<Self, sea_orm::DbErr> {
let account = parse_query_to_model::<account::Model, account::Entity>(res)?.into();
let flat = parse_query_to_model::<flat::Model, flat::Entity>(res)?;
let house = parse_query_to_model::<house::Model, house::Entity>(res)?;
Ok(Self {
account,
flat,
house,
})
}
} |
Beta Was this translation helpful? Give feedback.
-
Thank you for your sharing! I have great inspirations from it. I think it only works for one-to-one-to-one (and so on) cases, now I am convinced that this can be done with a composite struct API. |
Beta Was this translation helpful? Give feedback.
-
I stumbled upon this while trying to do something similar (but not this great) myself, thank you. I think these chains of one-to-one-to-one tables deserve this kind of support :) |
Beta Was this translation helpful? Give feedback.
-
@numfin After wrecking my brain for 3 hours, I just came across this and wanted to say thank you! |
Beta Was this translation helpful? Give feedback.
-
I hope i will help someone like me.
Motivation
I have 3 tables:
users
,apartments
,house
I want to select
users
and have access toapartment
andhouse
I looked at source code of
find_also_related()
and found private helper functionprepare_select_two()
.I copy-modified this function in my code like this
And now i am able to use it like this
All we left to do is just declare our new custom model:
Proposed Solutions
Please make this usefull "modified" function public :) It is very usefull
Additional Information
You can do all same above without prefixes, but final struct will have incorrect data if your models have similar column names.
Example:
Then your final data will be incorect:
Prefixes fixing that :)
I hope i helped ❤️
Beta Was this translation helpful? Give feedback.
All reactions