Relations¶
Learn how to work with relational data in ORMDB.
Relation Types¶
ORMDB supports three types of relations:
| Type | Example | Description |
|---|---|---|
| One-to-One | User → Profile | Each user has exactly one profile |
| One-to-Many | User → Posts | A user can have many posts |
| Many-to-Many | Users ↔ Teams | Users belong to many teams, teams have many users |
One-to-Many Relations¶
The most common relation type.
Schema¶
Querying¶
Inverse Relation¶
Query from the "many" side back to the "one":
One-to-One Relations¶
Schema¶
Querying¶
let query = GraphQuery::new("User")
.include(RelationInclude::new("profile"));
let result = client.query(query).await?;
for user in result.entities("User") {
if let Some(profile) = result.related_one(&user, "profile")? {
println!("{}'s bio: {}", user.get_string("name")?, profile.get_string("bio")?);
}
}
Many-to-Many Relations¶
Many-to-many relations require an edge entity (join table).
Schema¶
// Edge entity with additional fields
let team_member = EntityDef::new("TeamMember", "id")
.with_field(FieldDef::new("user_id", FieldType::Scalar(ScalarType::Uuid)))
.with_field(FieldDef::new("team_id", FieldType::Scalar(ScalarType::Uuid)))
.with_field(FieldDef::new("role", FieldType::Scalar(ScalarType::String)))
.with_field(FieldDef::new("joined_at", FieldType::Scalar(ScalarType::Timestamp)));
// Relations
let user_memberships = RelationDef::one_to_many("memberships", "User", "id", "TeamMember", "user_id");
let team_memberships = RelationDef::one_to_many("memberships", "Team", "id", "TeamMember", "team_id");
let membership_user = RelationDef::many_to_one("user", "TeamMember", "user_id", "User", "id");
let membership_team = RelationDef::many_to_one("team", "TeamMember", "team_id", "Team", "id");
Querying¶
// Get user's teams (through memberships)
let query = GraphQuery::new("User")
.include(RelationInclude::new("memberships")
.include(RelationInclude::new("team")));
let result = client.query(query).await?;
for user in result.entities("User") {
for membership in result.related(&user, "memberships") {
let team = result.related_one(&membership, "team")?;
let role = membership.get_string("role")?;
println!("{} is a {} in {}",
user.get_string("name")?,
role,
team.get_string("name")?);
}
}
const result = await client.query("User", {
includes: [
{
relation: "memberships",
includes: [{ relation: "team" }],
},
],
});
for (const user of result.entities) {
for (const membership of user.memberships || []) {
console.log(
`${user.name} is a ${membership.role} in ${membership.team?.name}`
);
}
}
Creating Many-to-Many¶
Nested Includes¶
Load multiple levels of relations:
// User → Posts → Comments → Author
let query = GraphQuery::new("User")
.with_fields(vec!["id", "name"])
.include(RelationInclude::new("posts")
.with_fields(vec!["id", "title"])
.include(RelationInclude::new("comments")
.with_fields(vec!["content"])
.include(RelationInclude::new("author")
.with_fields(vec!["name"]))));
Filtered and Sorted Includes¶
Next Steps¶
- Filtering - Filter relations and root entities
- Pagination - Paginate through large datasets
- Performance - Optimize relation queries