Fetching Relations
Relations can be fetched by calling a query builder's with
function.
The field modules of relation fields will contain fetch
functions, the results of which can be passed to with
.
The fetch
function of a many relation takes a Vec
of WhereParam
, while a single relation's fetch
function takes no arguments.
Once fetched, relation data can be accessed in two ways:
-
(Recommended) Use relation access functions on the parent struct. These will give you a
Result
containing a reference to the relation data. This is the recommended approach as theResult
error type will inform you that the field hasn't been fetched usingwith
. -
Use the data directly on the parent struct. This gives you direct access to the relation data, where it is wrapped inside an
Option
to determine whether it has been fetched. Doing this only recommended if you need to take ownership of the relation data, as dealing with nested options can be tricky and not as descriptive as the errors provided by accessor functions.
Whether a relation has been loaded can only be guaranteed at compile time if the accessor's Result
is not able to panic - ie. unwrap
, expect
etc are not called on it.
See Select & Include for completely type-safe ways of fetching relations.
The examples use the following schema:
model Post {
id String @id @default(cuid())
published Boolean
title String
content String?
desc String?
comments Comment[]
}
model Comment {
id String @id @default(cuid())
content String
post Post @relation(fields: [postID], references: [id])
postID String
}
Single Relations
In this example, the post
relation is loaded alongside a comment.
use prisma::{comment, post};
let comment: Option<comment::Data> = client
.comment()
.find_unique(comment::id::equals("0".to_string()))
.with(comment::post::fetch())
.exec()
.await
.unwrap();
// Since the above query includes a with() call
// the result will be an Ok()
let post: Result<post::Data, String> = comment.post();
Many Relations
In this example, a post
and its comments
are loaded.
use prisma::{comment, post};
let post: Option<post::Data> = client
.post()
.find_unique(post::id::equals("0".to_string()))
// Many relation requires Vec of filters as argument
.with(post::comments::fetch(vec![]))
.exec()
.await
.unwrap();
let comments: Result<Vec<comment::Data>, String> = post.comments();
Nested Relations
fetch
returns a query builder, so you can nest calls like with
to fetch nested relations.
In this example, a post is loaded with its comments, and each comment is loaded with the original post.
use prisam::{comment, post};
let post: post::Data = client
.post()
.find_unique(post::id::equals("0".to_string()))
.with(post::comments::fetch(vec![])
.with(comment::post::fetch())
)
.exec()
.await
.unwrap()
.unwrap();
// Safe since post::comments::fetch has been used
for comment in post.comments().unwrap() {
// Safe since comment::post::fetch has been used
let post = comment.post().unwrap();
assert_eq!(post.id, "0");
}