Skip to content

Commit 61ad808

Browse files
committed
feat(movie): add full-text search movie method #78
1 parent 041b0bf commit 61ad808

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

src/movie/constants/movie-index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const MOVIE_INDEX = 'movies';

src/movie/movie.controller.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ import { Paginated } from '../common/decorators/paginated.decorator';
1313
import { IQuery } from '../common/interfaces/query.interface';
1414
import { MovieAward } from './schemas/movie-award.schema';
1515
import { MovieAwardDocsResponseDto } from './dto/response/movie-award-docs.response.dto';
16+
import { SearchMovieDto } from './dto/search-movie.dto';
17+
import { SearchMovieResponseDto } from './dto/response/search-movie.response.dto';
1618

1719
@Controller('movie', 'Фильмы, сериалы, и т.д.')
1820
export class MovieController extends BaseControllerWithFindById(
1921
Movie,
2022
MovieDocsResponseDto,
21-
'Поиск тайтлов',
23+
'Универсальный поиск с фильтрами',
2224
`В этом методе вы можете составить запрос на получение фильма любой сложности.
2325
\nДля этого используете значения представленные ниже. Вы можете комбинировать поля, так же указывать множественные и специальные значения полей!
2426
\nОбратите внимание, что этот метод возвращает множество результатов, поэтому по-умолчанию будет возвращены только определенные поля.
@@ -28,6 +30,18 @@ export class MovieController extends BaseControllerWithFindById(
2830
super(movieService);
2931
}
3032

33+
@Version('1.2')
34+
@Get('search')
35+
@UseInterceptors(CacheInterceptor)
36+
@ApiOperation({
37+
summary: 'Полнотекстовый поиск',
38+
description: `Этот метод предназначен для полнотекстового поиска тайтлов по текстовому запросу. Он принимает только один параметр \`query\`. Если вам нужны фильтры, гибкость и множество результатов, используйте метод \`Универсальный поиск с фильтрами\` (findMany). В этом методе также не доступен выбор полей. А в ответ приходит упрощенная модель, которая подходит только для отображения результатов поиска.`,
39+
})
40+
async searchMovie(@Query() query: SearchMovieDto): Promise<SearchMovieResponseDto> {
41+
const data = await this.service.searchMovie(query);
42+
return data;
43+
}
44+
3145
@Get('random')
3246
@ApiOperation({
3347
summary: 'Получить рандомный тайтл из базы',

src/movie/movie.service.ts

+19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import { MovieAward, MovieAwardDocument } from './schemas/movie-award.schema';
1111
import { MovieAwardDocsResponseDto } from './dto/response/movie-award-docs.response.dto';
1212
import { DateTime } from 'luxon';
1313
import { MeiliService } from '../meili/meili.service';
14+
import { MeiliMovieEntity } from './entities/meili-movie.entity';
15+
import { SearchMovieResponseDto } from './dto/response/search-movie.response.dto';
16+
import { SearchMovieDto } from './dto/search-movie.dto';
17+
import { MOVIE_INDEX } from './constants/movie-index';
1418

1519
@Injectable()
1620
export class MovieService extends BaseService<Movie> {
@@ -22,6 +26,21 @@ export class MovieService extends BaseService<Movie> {
2226
super(movieModel);
2327
}
2428

29+
async searchMovie(dto: SearchMovieDto): Promise<SearchMovieResponseDto> {
30+
const offset = (dto.page - 1) * dto.limit;
31+
const searchResponse = await this.meiliService.search<MeiliMovieEntity>(dto.query, MOVIE_INDEX, dto.limit, offset);
32+
33+
const shortMovieResponseDtos = searchResponse.hits.map((movie) => new MeiliMovieEntity(movie));
34+
35+
return {
36+
docs: shortMovieResponseDtos,
37+
total: searchResponse.totalHits,
38+
limit: dto.limit,
39+
page: dto.page,
40+
pages: Math.ceil(searchResponse.totalHits / dto.limit),
41+
};
42+
}
43+
2544
async getRandomMovie(): Promise<Movie> {
2645
const currentYear = DateTime.local().year;
2746
const filter = {

0 commit comments

Comments
 (0)