Skip to content

Commit 0fb7e54

Browse files
committed
feat(person): add full-text search method #78
1 parent 13cd126 commit 0fb7e54

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

src/person/person.controller.ts

+19-1
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,31 @@ import { PersonDocsResponseDto } from './dto/person-docs.response';
99
import { PersonService } from './person.service';
1010
import { PersonAward } from './schemas/person-award.schema';
1111
import { Person } from './schemas/person.schema';
12+
import { SearchDto } from 'src/common/dto/query/search.dto';
13+
import { SearchPersonResponseDto } from './dto/search-person.response.dto';
1214

1315
@Controller('person', 'Актеры, режиссеры, операторы, и т.д')
14-
export class PersonController extends BaseControllerWithFindById(Person, PersonDocsResponseDto, 'Поиск персон') {
16+
export class PersonController extends BaseControllerWithFindById(
17+
Person,
18+
PersonDocsResponseDto,
19+
'Универсальный поиск персон с фильтрами',
20+
) {
1521
constructor(private readonly personService: PersonService) {
1622
super(personService);
1723
}
1824

25+
@Version('1.2')
26+
@Get('search')
27+
@UseInterceptors(CacheInterceptor)
28+
@ApiOperation({
29+
summary: 'Полнотекстовый поиск',
30+
description: `Этот метод предназначен для полнотекстового поиска персон по текстовому запросу. Он принимает только один параметр \`query\`. Если вам нужны фильтры, гибкость и множество результатов, используйте метод \`Универсальный поиск с фильтрами\` (findMany). В этом методе также не доступен выбор полей. А в ответ приходит упрощенная модель, которая подходит только для отображения результатов поиска.`,
31+
})
32+
async searchPerson(@Query() query: SearchDto): Promise<SearchPersonResponseDto> {
33+
const data = await this.service.searchPerson(query);
34+
return data;
35+
}
36+
1937
@Version('1.1')
2038
@Get('awards')
2139
@UseInterceptors(CacheInterceptor)

src/person/person.module.ts

+2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import { PersonController } from './person.controller';
44
import { MongooseModule } from '@nestjs/mongoose';
55
import { Person, PersonSchema } from './schemas/person.schema';
66
import { PersonAward, PersonAwardSchema } from './schemas/person-award.schema';
7+
import { MeiliModule } from 'src/meili/meili.module';
78

89
@Module({
910
imports: [
1011
MongooseModule.forFeature([
1112
{ name: Person.name, schema: PersonSchema },
1213
{ name: PersonAward.name, schema: PersonAwardSchema },
1314
]),
15+
MeiliModule,
1416
],
1517
controllers: [PersonController],
1618
providers: [PersonService],

src/person/person.service.ts

+26
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,42 @@ import { IQuery } from 'src/common/interfaces/query.interface';
66
import { Person, PersonDocument } from 'src/person/schemas/person.schema';
77
import { PersonAwardDocsResponseDto } from './dto/person-award-docs.response.dto';
88
import { PersonAward, PersonAwardDocument } from './schemas/person-award.schema';
9+
import { SearchDto } from 'src/common/dto/query/search.dto';
10+
import { SearchPersonResponseDto } from './dto/search-person.response.dto';
11+
import { MeiliService } from 'src/meili/meili.service';
12+
import { MeiliPersonEntity } from './entities/meili-person.entity';
13+
import { PERSON_INDEX } from './constants/person-index';
914

1015
@Injectable()
1116
export class PersonService extends BaseService<Person> {
1217
constructor(
1318
@InjectModel(Person.name) private readonly personModel: Model<PersonDocument>,
1419
@InjectModel(PersonAward.name) private readonly personAwardModel: Model<PersonAwardDocument>,
20+
private readonly meiliService: MeiliService,
1521
) {
1622
super(personModel);
1723
}
1824

25+
async searchPerson(dto: SearchDto): Promise<SearchPersonResponseDto> {
26+
const offset = (dto.page - 1) * dto.limit;
27+
const searchResponse = await this.meiliService.search<MeiliPersonEntity>(
28+
dto.query,
29+
PERSON_INDEX,
30+
dto.limit,
31+
offset,
32+
);
33+
34+
const personEntities = searchResponse.hits.map((person) => new MeiliPersonEntity(person));
35+
36+
return {
37+
docs: personEntities,
38+
total: searchResponse.totalHits,
39+
limit: dto.limit,
40+
page: dto.page,
41+
pages: Math.ceil(searchResponse.totalHits / dto.limit),
42+
};
43+
}
44+
1945
async findManyAwards(query: IQuery): Promise<PersonAwardDocsResponseDto> {
2046
const [total, docs] = await Promise.all([
2147
this.personAwardModel.countDocuments(query.filter),

0 commit comments

Comments
 (0)