Repository navigation
Add recommendations - #17
Conversation
There was a problem hiding this comment.
Кирилл, спасибо! 🙌 Алгоритм понятный, тесты Практикума для ветки проходят все, а README с примерами запросов - огонь.
Две вещи нужно поправить до мержа:
- Пока не вливай: после режиссёров в develop у тебя падают тесты UserDbStorageTest. Git конфликта не покажет, а зелёная галочка CI старая - проверяла ветку до режиссёров. Подробности в комментарии к
@Import. - Фильмы в рекомендациях приходят без жанров и режиссёров — общий набор тестов Практикума на финальном PR это ловит.
И на подходе лента Даши.
После неё при подтягивании develop будут конфликты в README, UserController и UserService - оставляем всё от обоих, только в UserController проверь, что у метода getFeed осталась закрывающая скобка.
И ещё одно невидимое место: FeedDbStorageTest поднимает UserDbStorage, а тот у тебя теперь требует FilmRowMapper - без него падают тесты ленты.
Если запрос фильмов переедет в FilmDbStorage (см. комментарий про жанры), этой проблемы просто не будет.
Остальное - мелочи и один мой уточняющий вопрос.
Когда поправишь - подтяни develop, дождись зелёного CI, и после второго апрува вливай через Squash and merge с заголовком
feat: add film recommendations based on similar users (#17)
| @AutoConfigureTestDatabase | ||
| @Import({UserDbStorage.class, UserRowMapper.class}) | ||
| @Import({UserDbStorage.class, UserRowMapper.class, FilmRowMapper.class, | ||
| FilmDbStorage.class, GenreRowMapper.class}) |
There was a problem hiding this comment.
После того как в develop влились режиссёры, FilmDbStorage требует ещё DirectorRowMapper, а здесь его нет.
Если подтянуть новой develop, то все 14 тестов этого класса падают на подъёме контекста. Git конфликта не покажет, а зелёная галочка CI сейчас старая: она проверяла ветку до режиссёров.
Нужно подтянуть develop и добавить DirectorRowMapper в @Import.
There was a problem hiding this comment.
Вернул @import.
Запрос рекомендаций в FilmDbStorage.
FilmRowMapper, DirectorRowMapper теперь не нужен.
| } | ||
|
|
||
| Long similarUserId = similarUserIds.getFirst(); | ||
| return jdbc.query(FIND_RECOMMENDATIONS_QUERY, filmMapper, similarUserId, userId); |
There was a problem hiding this comment.
Фильмы в рекомендациях приходят без жанров и режиссёров: тут только FilmRowMapper, а жанры и режиссёры в проекте подгружает FilmDbStorage.
Общий набор тестов Практикума на финальном PR develop -> main это проверяет: в "User id=1 Get film recommendations from user id=2" ждут у фильма 2 жанра, а приходит 0.
Фильмы у нас собирает FilmDbStorage - если запрос фильмов для рекомендаций переедет туда, жанры и режиссёры подтянутся тем же путём, что везде.
А UserDbStorage заодно перестанет зависеть от фильмов: сейчас любому тесту, который поднимает UserDbStorage, приходится тащить и FilmRowMapper.
There was a problem hiding this comment.
Перенёс запрос фильмов для рекомендаций в FilmDbStorage
Добавил тест shouldReturnRecommendationsWithGenres
| + "WHERE fl1.user_id = ? AND fl2.user_id <> ? " | ||
| + "GROUP BY fl2.user_id " | ||
| + "ORDER BY common DESC, fl2.user_id " | ||
| + "LIMIT 1"; |
There was a problem hiding this comment.
Тут скорее вопрос, а не блокировочный момент: если у двух пользователей пересечение одинаковое, берём только одного - с меньшим id, а фильмы второго теряются.
В ТЗ "найти пользователей с максимальным количеством пересечений", во множественном числе.
Тесты Практикума это не проверяют, так что можно оставить, мне любопытно стало, осознанно ли так было сделано)
There was a problem hiding this comment.
Исправил на множественное число,
| User boris = createUser("boris"); | ||
| Film first = createFilm("Первый"); | ||
| Film second = createFilm("Второй"); | ||
| userStorage.addFriend(anna.getId(), boris.getId()); |
There was a problem hiding this comment.
Дружба вроде как рекомендациях не участвует - строчку можно убрать, чтобы тест не наводил на мысль, что рекомендации зависят от друзей.
| - Режиссёры: таблицы `directors` и `film_director`, у фильма — список режиссёров. | ||
| - Рекомендации фильмов: два SQL-запроса — поиск самого похожего пользователя | ||
| по пересечению лайков и его фильмы, которых нет у пользователя. | ||
| - Все эндпоинты покрыты интеграционными тестами (`@JdbcTest`). |
There was a problem hiding this comment.
Тут, кажется, "хранилища": @JdbcTest тестирует хранилища, а не эндпоинты.
А так раздел "Этап 4" классный - в финальном проходе README допишем туда остальные фичи группового проекта)
There was a problem hiding this comment.
Поправил на хранилища
DariaPrindina
left a comment
There was a problem hiding this comment.
Посмотрела, согласна с замечаниями Ксюши, нового добавить нечего. Особенно поддерживаю перенос запроса в FilmDbStorage: тогда и жанры с режиссёрами подтянутся, и тесты ленты не будут зависеть от FilmRowMapper. После правок посмотрю ещё раз и апрувну
ksupyl
left a comment
There was a problem hiding this comment.
Кирилл, спасибо, что всё разобрал)
Запрос переехал в FilmDbStorage, жанры подтягиваются, ничьи учитываются - крутяк!
Осталось три момента, подробности в комментариях:
- при мерже develop случайно удалились мои тесты на удаление в FilmDbStorageTest - их нужно вернуть;
- у рекомендованных фильмов нет режиссёров;
- README описывает старый алгоритм.
Если это поправить, то сразу апрув без вариантов)
| assertTrue(filmStorage.findById(film.getId()).isEmpty()); | ||
| } | ||
|
|
||
| // Без ON DELETE CASCADE удаление упало бы на внешних ключах film_genres и film_likes |
There was a problem hiding this comment.
Кажется, при мерже develop сюда случайно уехали мои тесты на удаление -shouldDeleteFilmWithGenresAndLikes, shouldNotCountLikesOfDeletedUser и shouldThrowWhenDeletingUnknownFilm (и импорт NotFoundException).
Верни их, пожалуйста. С твоими тестами рекомендаций они прекрасно уживаются)
|
|
||
| List<Film> films = jdbc.query(sql, mapper, params.toArray()); | ||
| // Жанры подтягиваются тем же путём, что и у остальных списочных запросов | ||
| loadGenresForFilms(films); |
There was a problem hiding this comment.
Жанры теперь есть)
А режиссёры у рекомендованных фильмов всё ещё пустые: в остальных методах со списками фильмов рядом стоит и loadDirectors(films), а здесь его нет.
| WHERE fl1.user_id = 1 AND fl2.user_id <> 1 | ||
| GROUP BY fl2.user_id | ||
| ORDER BY common DESC, fl2.user_id | ||
| LIMIT 1; |
There was a problem hiding this comment.
Тут описан старый вариант - с одним самым похожим пользователем.
Сейчас берутся все с максимальным пересечением: поправь, пожалуйста, пример и строчку про рекомендации в "Этап 4".
ksupyl
left a comment
There was a problem hiding this comment.
Кирилл, всё на месте)
Тесты на удаление вернулись, режиссёры у рекомендаций подтягиваются, в README новый алгоритм.
Апрув! Как будет второй апрув - вливай через Squash and merge, заголовок
feat: add film recommendations based on similar users (#17)
Что сделано
Добавлен эндпоинт
GET /users/{id}/recommendationsдля рекомендации фильмовна основе пользователей с похожими вкусами.
Алгоритм:
Детали
берётся меньший
id(ORDER BY common DESC, fl2.user_id).вся логика в
UserDbStorage, ничего не «протекает» в сервис или контроллер.