Skip to content

Commit

Permalink
⚡️ Update: 검색 API 페이징 추가
Browse files Browse the repository at this point in the history
기본 검색, 텍스트 검색은 커서 기반 페이징, 임베딩 검색은 오프셋 기반 페이징 적용, DefaultValuePipe로 쿼리에 기본값 설정

#
  • Loading branch information
ks1ksi committed Aug 7, 2023
1 parent 0bc52b4 commit f9c3ca2
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 13 deletions.
71 changes: 62 additions & 9 deletions src/document/document.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Body,
Controller,
DefaultValuePipe,
Delete,
Get,
Logger,
Expand Down Expand Up @@ -123,19 +124,20 @@ export class DocumentController {
required: false,
type: Number,
description: '한 번에 받을 문서의 개수. 최대 20개까지 가능. 기본값은 20.',
example: 20,
})
findAllWithCursor(
@GetUid() uid: string,
@Query('cursor') cursor?: Date,
@Query('doc-id') docId?: string,
@Query('limit', ParseIntPipe) limit?: number,
@Query('cursor', new DefaultValuePipe(new Date())) cursor: Date,
@Query(
'doc-id',
new DefaultValuePipe('ffffffff-ffff-ffff-ffff-ffffffffffff'),
)
docId: string,
@Query('limit', new DefaultValuePipe(20), ParseIntPipe) limit: number,
): Promise<DocumentDto[]> {
this.logger.debug(cursor);
this.logger.debug(docId);
cursor = cursor ? cursor : new Date();
docId = docId ? docId : 'ffffffff-ffff-ffff-ffff-ffffffffffff';
limit = limit && limit <= 20 ? limit : 20;
limit = limit > 20 ? 20 : limit;
return this.documentService.findByCursor(uid, cursor, docId, limit);
}

Expand All @@ -162,12 +164,26 @@ export class DocumentController {
type: String,
description: '임베딩 검색할 쿼리',
})
@ApiQuery({
name: 'limit',
required: false,
type: Number,
description: '한 번에 받을 문서의 개수. 최대 20개까지 가능. 기본값은 20.',
})
@ApiQuery({
name: 'offset',
required: false,
type: Number,
description: '검색 결과의 시작 인덱스. 기본값은 0.',
})
searchByEmbedding(
@GetUid() uid: string,
@Query('query') query: string,
@Query('limit', new DefaultValuePipe(20), ParseIntPipe) limit: number,
@Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
): Promise<DocumentDto[]> {
this.logger.debug(`query: ${query}`);
return this.documentService.findByEmbedding(uid, query);
return this.documentService.findByEmbedding(uid, query, limit, offset);
}

@Get('search/text')
Expand All @@ -177,10 +193,47 @@ export class DocumentController {
type: String,
description: '텍스트 검색할 쿼리',
})
@ApiQuery({
name: 'cursor',
required: false,
type: Date,
description:
'이전에 받은 문서들 중 마지막 문서의 updatedAt. 이 값이 없으면 현재 시간으로.',
example: '2021-01-01T00:00:00.000Z',
})
@ApiQuery({
name: 'doc-id',
required: false,
type: String,
description:
'이전에 받은 문서들 중 마지막 문서의 docId. 이 값이 없으면 가장 큰 UUID 값으로.',
example: 'ffffffff-ffff-ffff-ffff-ffffffffffff',
})
@ApiQuery({
name: 'limit',
required: false,
type: Number,
description: '한 번에 받을 문서의 개수. 최대 20개까지 가능. 기본값은 20.',
example: 20,
})
searchByQuery(
@GetUid() uid: string,
@Query('query') query: string,
@Query('cursor', new DefaultValuePipe(new Date())) cursor: Date,
@Query(
'doc-id',
new DefaultValuePipe('ffffffff-ffff-ffff-ffff-ffffffffffff'),
)
docId: string,
@Query('limit', new DefaultValuePipe(20), ParseIntPipe) limit: number,
): Promise<DocumentDto[]> {
return this.documentService.findByFullText(uid, query);
limit = limit > 20 ? 20 : limit;
return this.documentService.findByFullText(
uid,
query,
cursor,
docId,
limit,
);
}
}
40 changes: 36 additions & 4 deletions src/document/document.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ export class DocumentService {
return new DocumentDto(document);
}

async findByEmbedding(uid: string, query: string): Promise<DocumentDto[]> {
async findByEmbedding(
uid: string,
query: string,
limit: number,
offset: number,
): Promise<DocumentDto[]> {
const user = await this.getUserByUid(uid);
const vec: number[] = await this.openAiService.getEmbedding(query);
const vector: string = JSON.stringify(vec);
Expand All @@ -103,7 +108,8 @@ export class DocumentService {
left join tag as t on dt."B" = t.id
group by d.id, subquery.min_distance
order by subquery.min_distance
limit 5;
limit ${limit}
offset ${offset * limit};
`;

this.logger.debug(`rawItems: ${JSON.stringify(rawItems)}`);
Expand All @@ -122,14 +128,35 @@ export class DocumentService {
}));
}

async findByFullText(uid: string, query: string): Promise<DocumentDto[]> {
async findByFullText(
uid: string,
query: string,
cursor: Date,
docId: string,
take: number,
): Promise<DocumentDto[]> {
const user = await this.getUserByUid(uid);
const documents = await this.prisma.document.findMany({
where: {
AND: [
{
userId: user.id,
},
{
OR: [
{
updatedAt: {
lt: cursor,
},
},
{
updatedAt: cursor,
docId: {
lt: docId,
},
},
],
},
{
OR: [
{
Expand All @@ -149,7 +176,12 @@ export class DocumentService {
include: {
tags: true,
},
take: 5,
orderBy: [
{
updatedAt: 'desc',
},
],
take,
});

return documents.map((document) => new DocumentDto(document));
Expand Down

0 comments on commit f9c3ca2

Please sign in to comment.