Добавить данные в результаты дизеля, когда пользователь вошел в систему без использования N + 1 запросов - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть база данных mov ie, где пользователи могут отмечать фильмы как просмотренные и избранные с помощью следующих моделей:

#[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,
}

Как мне поступить, если я хочу перечислить 100 последних добавленных фильмов в базу данных, а также включить пользовательские данные для каждого mov ie, если пользователь вошел в систему, избегая при этом проблемы с запросом N + 1?

Думаю, я мог бы добавить еще одну структуру для movies таблица, в которую я также включаю необязательные данные пользователя, но я не уверен, как бы я использовал их вместе с дизельным ORM.

struct UserData {
   favorite: bool,
   watched: Option<DateTime>,
}

struct UserMovie {
   id: i32,
   user_data: Option<UserData>,
}

1 Ответ

0 голосов
/ 21 апреля 2020

Использование 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()
...