我有一个电影数据库,用户可以使用以下模型将电影标记为已观看和收藏的电影:
#[derive(Serialize, Deserialize, Identifiable, Queryable, Associations)]
#[table_name = "movies"]
struct Movie {
id: 32
}
#[derive(Serialize, Deserialize, Identifiable, Queryable, Associations)]
#[table_name = "users"]
struct User {
id: 32
}
#[derive(Serialize, Deserialize, Identifiable, Queryable, Associations)]
#[table_name = "favorite_movies"]
struct FavoriteMovie {
movie_id: i32,
user_id: i32,
}
#[derive(Serialize, Deserialize, Identifiable, Queryable, Associations)]
#[table_name = "watched_movies"]
struct WatchedMovie {
movie_id: i32,
user_id: i32,
date: DateTime,
}
如果要登录,同时又要避免N + 1查询的问题,该如何处理要列出数据库中最近添加的100部电影并包括每部电影的用户数据的情况?
我在想可以为
movies
表添加另一个结构,其中还包括可选的用户数据,但是我不确定如何将其与Diesel ORM一起使用。struct UserData {
favorite: bool,
watched: Option<DateTime>,
}
struct UserMovie {
id: i32,
user_data: Option<UserData>,
}
最佳答案
使用 left_join
:
struct UserMovie {
movie: Movie,
favorite_movie: Option<FavoriteMovie>,
watched_movie: Option<WatchedMovie>,
}
let conn = get_db_connection();
let user_movies: Vec<UserMovie> = movies::table
.left_join(
favorite_movies::table.on(favorite_movies::movie_id
.eq(movies::id)
.and(favorite_movies::user_id.eq(user_id))),
)
.left_join(
watched_movies::table.on(watched_movies::movie_id
.eq(movies::id)
.and(watched_movies::user_id.eq(user_id))),
)
.load(conn)?
.into_iter()
.map(
|(movie, favorite_movie, watched_movie): (Movie, Option<FavoriteMovie>, Option<WatchedMovie>)| UserMovie {
movie,
favorite_movie,
watched_movie,
}
)
.collect()
关于rust - 在用户不使用N + 1查询的情况下登录时将数据添加到Diesel结果中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61291050/