Map field to id of other table (FOREIGN KEY)
examples/surrealdb/map-field-to-id-of-other-table/src/main.rs
use serde::{Deserialize, Serialize}; use surrealdb::engine::local::{Db, Mem}; use surrealdb::sql::{Id, Thing}; use surrealdb::Surreal; const DANCE: &str = "dance"; const STUDENT: &str = "student"; #[derive(Debug, Serialize, Deserialize)] struct DanceClass { id: Thing, name: String, } #[derive(Debug, Serialize, Deserialize)] struct Student { id: Thing, name: String, classes: Vec<Thing>, } #[derive(Debug, Deserialize)] #[allow(dead_code)] struct StudentClasses { id: Thing, name: String, classes: Vec<DanceClass>, } #[tokio::main] async fn main() -> surrealdb::Result<()> { let db = Surreal::new::<Mem>(()).await?; db.use_ns("namespace").use_db("database").await?; add_classes(&db).await?; let classes = get_classes(&db).await?; // the next lines are valid but then will lead to an error when fetching the data // classes.push(DanceClass { // id: Thing::from((DANCE, Id::rand())), // name: String::from("Belly dance"), // }); add_students(&db, classes).await?; show_students_in_classes(&db).await?; Ok(()) } async fn add_classes(db: &Surreal<Db>) -> surrealdb::Result<()> { for name in ["Introduction to Dancing", "Flamenco"] { let classes: Vec<DanceClass> = db .create(DANCE) .content(DanceClass { id: Thing::from((DANCE, Id::rand())), name: name.to_owned(), }) .await?; println!("class added: {classes:?}"); } Ok(()) } async fn get_classes(db: &Surreal<Db>) -> surrealdb::Result<Vec<DanceClass>> { let sql = "SELECT * FROM dance"; let mut results = db.query(sql).await?; let classes: Vec<DanceClass> = results.take(0)?; for class in &classes { println!("get_classes: {class:?}"); } Ok(classes) } async fn add_students(db: &Surreal<Db>, classes: Vec<DanceClass>) -> surrealdb::Result<()> { let students: Vec<Student> = db .create(STUDENT) .content(Student { id: Thing::from((STUDENT, Id::rand())), name: "Jane Doe".to_owned(), classes: classes.into_iter().map(|class| class.id).collect(), }) .await?; println!("student added: {students:#?}"); Ok(()) } async fn show_students_in_classes(db: &Surreal<Db>) -> surrealdb::Result<()> { let sql = format!("SELECT * FROM {STUDENT} FETCH classes"); let mut results = db.query(sql).await?; let students: Vec<StudentClasses> = results.take(0)?; println!("Students: {students:#?}"); Ok(()) }
class added: [DanceClass { id: Thing { tb: "dance", id: String("gjjhx7vr62vaiqr49ivr") }, name: "Introduction to Dancing" }] class added: [DanceClass { id: Thing { tb: "dance", id: String("c4v2dpfzsreg1u5nleeq") }, name: "Flamenco" }] get_classes: DanceClass { id: Thing { tb: "dance", id: String("c4v2dpfzsreg1u5nleeq") }, name: "Flamenco" } get_classes: DanceClass { id: Thing { tb: "dance", id: String("gjjhx7vr62vaiqr49ivr") }, name: "Introduction to Dancing" } student added: [ Student { id: Thing { tb: "student", id: String( "h8c5rpmyhb3p3l0yu7al", ), }, name: "Jane Doe", classes: [ Thing { tb: "dance", id: String( "c4v2dpfzsreg1u5nleeq", ), }, Thing { tb: "dance", id: String( "gjjhx7vr62vaiqr49ivr", ), }, ], }, ] Students: [ StudentClasses { id: Thing { tb: "student", id: String( "h8c5rpmyhb3p3l0yu7al", ), }, name: "Jane Doe", classes: [ DanceClass { id: Thing { tb: "dance", id: String( "c4v2dpfzsreg1u5nleeq", ), }, name: "Flamenco", }, DanceClass { id: Thing { tb: "dance", id: String( "gjjhx7vr62vaiqr49ivr", ), }, name: "Introduction to Dancing", }, ], }, ]