Skip to content

Add recommendations - #17

Merged
Kirill-Kazantcev merged 6 commits into
developfrom
add-recommendations
Oct 11, 2026
Merged

Kirill-Kazantcev merged 6 commits into
developfrom
add-recommendations

Conversation

@Kirill-Kazantcev

@Kirill-Kazantcev Kirill-Kazantcev commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Что сделано

Добавлен эндпоинт GET /users/{id}/recommendations для рекомендации фильмов
на основе пользователей с похожими вкусами.

Алгоритм:

  1. Находим пользователя с максимальным пересечением по лайкам.
  2. Возвращаем его фильмы, которых нет у нашего пользователя.

Детали

  • Рекомендации не хранятся в БД - вычисляются на лету. Схема не менялась.
  • Детерминированный выбор похожего пользователя: при равном пересечении
    берётся меньший id (ORDER BY common DESC, fl2.user_id).
  • В проекте остаются только три SQL-константы для рекомендаций,
    вся логика в UserDbStorage, ничего не «протекает» в сервис или контроллер.

@Kirill-Kazantcev
Kirill-Kazantcev changed the base branch from main to develop October 8, 2026 22:21

@ksupyl ksupyl left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Кирилл, спасибо! 🙌 Алгоритм понятный, тесты Практикума для ветки проходят все, а README с примерами запросов - огонь.

Две вещи нужно поправить до мержа:

  1. Пока не вливай: после режиссёров в develop у тебя падают тесты UserDbStorageTest. Git конфликта не покажет, а зелёная галочка CI старая - проверяла ветку до режиссёров. Подробности в комментарии к @Import.
  2. Фильмы в рекомендациях приходят без жанров и режиссёров — общий набор тестов Практикума на финальном 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})

@ksupyl ksupyl Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

После того как в develop влились режиссёры, FilmDbStorage требует ещё DirectorRowMapper, а здесь его нет.
Если подтянуть новой develop, то все 14 тестов этого класса падают на подъёме контекста. Git конфликта не покажет, а зелёная галочка CI сейчас старая: она проверяла ветку до режиссёров.

Нужно подтянуть develop и добавить DirectorRowMapper в @Import.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вернул @import.
Запрос рекомендаций в FilmDbStorage.
FilmRowMapper, DirectorRowMapper теперь не нужен.

}

Long similarUserId = similarUserIds.getFirst();
return jdbc.query(FIND_RECOMMENDATIONS_QUERY, filmMapper, similarUserId, userId);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Фильмы в рекомендациях приходят без жанров и режиссёров: тут только FilmRowMapper, а жанры и режиссёры в проекте подгружает FilmDbStorage.
Общий набор тестов Практикума на финальном PR develop -> main это проверяет: в "User id=1 Get film recommendations from user id=2" ждут у фильма 2 жанра, а приходит 0.

Фильмы у нас собирает FilmDbStorage - если запрос фильмов для рекомендаций переедет туда, жанры и режиссёры подтянутся тем же путём, что везде.
А UserDbStorage заодно перестанет зависеть от фильмов: сейчас любому тесту, который поднимает UserDbStorage, приходится тащить и FilmRowMapper.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Перенёс запрос фильмов для рекомендаций в FilmDbStorage
Добавил тест shouldReturnRecommendationsWithGenres

+ "WHERE fl1.user_id = ? AND fl2.user_id <> ? "
+ "GROUP BY fl2.user_id "
+ "ORDER BY common DESC, fl2.user_id "
+ "LIMIT 1";

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут скорее вопрос, а не блокировочный момент: если у двух пользователей пересечение одинаковое, берём только одного - с меньшим id, а фильмы второго теряются.
В ТЗ "найти пользователей с максимальным количеством пересечений", во множественном числе.
Тесты Практикума это не проверяют, так что можно оставить, мне любопытно стало, осознанно ли так было сделано)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Исправил на множественное число,

User boris = createUser("boris");
Film first = createFilm("Первый");
Film second = createFilm("Второй");
userStorage.addFriend(anna.getId(), boris.getId());

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Дружба вроде как рекомендациях не участвует - строчку можно убрать, чтобы тест не наводил на мысль, что рекомендации зависят от друзей.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Убрал

Comment thread README.md Outdated
- Режиссёры: таблицы `directors` и `film_director`, у фильма — список режиссёров.
- Рекомендации фильмов: два SQL-запроса — поиск самого похожего пользователя
по пересечению лайков и его фильмы, которых нет у пользователя.
- Все эндпоинты покрыты интеграционными тестами (`@JdbcTest`).

@ksupyl ksupyl Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут, кажется, "хранилища": @JdbcTest тестирует хранилища, а не эндпоинты.
А так раздел "Этап 4" классный - в финальном проходе README допишем туда остальные фичи группового проекта)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Поправил на хранилища

@DariaPrindina
DariaPrindina self-requested a review October 9, 2026 16:30

@DariaPrindina DariaPrindina left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Посмотрела, согласна с замечаниями Ксюши, нового добавить нечего. Особенно поддерживаю перенос запроса в FilmDbStorage: тогда и жанры с режиссёрами подтянутся, и тесты ленты не будут зависеть от FilmRowMapper. После правок посмотрю ещё раз и апрувну

@ksupyl ksupyl left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Кирилл, спасибо, что всё разобрал)
Запрос переехал в FilmDbStorage, жанры подтягиваются, ничьи учитываются - крутяк!

Осталось три момента, подробности в комментариях:

  1. при мерже develop случайно удалились мои тесты на удаление в FilmDbStorageTest - их нужно вернуть;
  2. у рекомендованных фильмов нет режиссёров;
  3. README описывает старый алгоритм.

Если это поправить, то сразу апрув без вариантов)

assertTrue(filmStorage.findById(film.getId()).isEmpty());
}

// Без ON DELETE CASCADE удаление упало бы на внешних ключах film_genres и film_likes

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Кажется, при мерже develop сюда случайно уехали мои тесты на удаление -shouldDeleteFilmWithGenresAndLikes, shouldNotCountLikesOfDeletedUser и shouldThrowWhenDeletingUnknownFilm (и импорт NotFoundException).

Верни их, пожалуйста. С твоими тестами рекомендаций они прекрасно уживаются)


List<Film> films = jdbc.query(sql, mapper, params.toArray());
// Жанры подтягиваются тем же путём, что и у остальных списочных запросов
loadGenresForFilms(films);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Жанры теперь есть)
А режиссёры у рекомендованных фильмов всё ещё пустые: в остальных методах со списками фильмов рядом стоит и loadDirectors(films), а здесь его нет.

Comment thread README.md Outdated
WHERE fl1.user_id = 1 AND fl2.user_id <> 1
GROUP BY fl2.user_id
ORDER BY common DESC, fl2.user_id
LIMIT 1;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут описан старый вариант - с одним самым похожим пользователем.
Сейчас берутся все с максимальным пересечением: поправь, пожалуйста, пример и строчку про рекомендации в "Этап 4".

@ksupyl ksupyl left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Кирилл, всё на месте)
Тесты на удаление вернулись, режиссёры у рекомендаций подтягиваются, в README новый алгоритм.

Апрув! Как будет второй апрув - вливай через Squash and merge, заголовок
feat: add film recommendations based on similar users (#17)

@Kirill-Kazantcev
Kirill-Kazantcev merged commit 7d5e051 into develop Oct 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Функциональность «Рекомендации». 3 SP

3 participants