Skip to content

Commit e4babda

Browse files
committed
feat: add query transfom pipe
1 parent f974fa0 commit e4babda

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface IQuery {
2+
query?: any;
3+
sort?: any;
4+
select?: any;
5+
limit?: number;
6+
skip?: number;
7+
}

src/common/pipes/query.pipe.ts

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import {
2+
PipeTransform,
3+
Injectable,
4+
ArgumentMetadata,
5+
BadRequestException,
6+
} from '@nestjs/common';
7+
import { Types } from 'mongoose';
8+
import { IQuery } from '../interfaces/query.interface';
9+
10+
const SYSTEM_KEYS = [
11+
'sortField',
12+
'sortType',
13+
'selectFields',
14+
'page',
15+
'limit',
16+
'field',
17+
'search',
18+
];
19+
20+
@Injectable()
21+
export class QueryPipe implements PipeTransform {
22+
transform(value: any, metadata: ArgumentMetadata): IQuery {
23+
const query: any = {};
24+
const sort: any = {};
25+
const select: any = {};
26+
let page = 1;
27+
let limit = 10;
28+
29+
// Парсим параметры для поиска
30+
if (value.search) {
31+
if (Array.isArray(value.field) && Array.isArray(value.search)) {
32+
value.field.forEach((field: string, index: number) => {
33+
query[field] = value.search[index];
34+
});
35+
} else if (
36+
typeof value.field === 'string' &&
37+
typeof value.search === 'string'
38+
) {
39+
query[value.field] = value.search;
40+
} else {
41+
throw new BadRequestException('Invalid search parameters');
42+
}
43+
}
44+
45+
// Парсим параметры для поиска
46+
for (const [key, val] of Object.entries(value)) {
47+
if (SYSTEM_KEYS.includes(key)) {
48+
query[key] = val;
49+
}
50+
}
51+
52+
// Парсим параметры для сортировки
53+
if (value.sortField) {
54+
const fields = Array.isArray(value.sortField)
55+
? value.sortField
56+
: [value.sortField];
57+
const types = Array.isArray(value.sortType)
58+
? value.sortType
59+
: [value.sortType];
60+
61+
fields.forEach((field: string, index: number) => {
62+
sort[field] = types[index] === '1' ? 1 : -1;
63+
});
64+
}
65+
66+
// Парсим параметры для выбора полей
67+
if (value.selectFields) {
68+
const fields = Array.isArray(value.selectFields)
69+
? value.selectFields.join(' ')
70+
: value.selectFields;
71+
fields.split(' ').forEach((field: string) => {
72+
select[field] = 1;
73+
});
74+
}
75+
76+
// Парсим параметры для пагинации
77+
if (value.page) {
78+
page = parseInt(value.page, 10);
79+
}
80+
if (value.limit) {
81+
limit = parseInt(value.limit, 10);
82+
}
83+
84+
return { query, sort, select, limit, skip: (page - 1) * limit };
85+
}
86+
}

src/movie/movie.controller.ts

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
Query,
77
SerializeOptions,
88
UseInterceptors,
9+
UsePipes,
910
} from '@nestjs/common';
1011
import { MovieService } from './movie.service';
1112
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@@ -15,6 +16,7 @@ import { MovieDocsResponseDto } from './dto/movie-docs.response.dto';
1516
import { Movie } from './schemas/movie.schema';
1617
import { ToolsQueryDto } from '../common/dto/query/tools.query.dto';
1718
import { IFindManyMovie } from './interfaces/find-many-movie.interface';
19+
import { QueryPipe } from 'src/common/pipes/query.pipe';
1820

1921
@UseInterceptors(ClassSerializerInterceptor)
2022
@SerializeOptions({ excludeExtraneousValues: true })
@@ -24,12 +26,15 @@ export class MovieController {
2426
constructor(private readonly movieService: MovieService) {}
2527

2628
@Get()
29+
@UsePipes(new QueryPipe())
2730
@ApiOperation({ summary: 'Поиск фильмов' })
2831
@ApiDotNotationQuery(ToolsQueryDto, PaginatedQueryDto, Movie)
2932
@ApiResponse({ type: MovieDocsResponseDto, isArray: true })
3033
async finManyByQuery(
3134
@Query() filters: IFindManyMovie,
3235
): Promise<MovieDocsResponseDto> {
36+
console.log(filters);
37+
3338
return this.movieService.findMany(filters);
3439
}
3540

0 commit comments

Comments
 (0)