Skip to main content
Version: 0.4.x

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(" ")
);