Chained Relations
If you have multiple join paths between two entities or have complex joins that chain through multiple entities, you can define it with Linked
. Take this as a simple example, where we join cake and filling via an intermediate cake_filling table.
#[derive(Debug)]
pub struct CakeToFilling;
impl Linked for CakeToFilling {
type FromEntity = cake::Entity;
type ToEntity = filling::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![
cake_filling::Relation::Cake.def().rev(),
cake_filling::Relation::Filling.def(),
]
}
}
Lazy Loading
Use the find_linked
method.
let cake_model = cake::Model {
id: 12,
name: "".to_owned(),
};
assert_eq!(
cake_model
.find_linked(cake::CakeToFilling)
.build(DbBackend::MySql)
.to_string(),
[
r#"SELECT `filling`.`id`, `filling`.`name`"#,
r#"FROM `filling`"#,
r#"INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#,
r#"INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`"#,
r#"WHERE `cake`.`id` = 12"#,
]
.join(" ")
);
Eager Loading
Use the find_also_linked
method.
assert_eq!(
cake::Entity::find()
.find_also_linked(cake::CakeToFilling)
.build(DbBackend::MySql)
.to_string(),
[
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
"`filling`.`id` AS `B_id`, `filling`.`name` AS `B_name`",
"FROM `cake`",
"LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`",
"LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
]
.join(" ")
);