From 03ea3838a6cfbd37a8d5092f81fef6bfb6b5397b Mon Sep 17 00:00:00 2001 From: Seungil Kim Date: Tue, 12 Sep 2023 01:44:10 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Feat:=20=EC=BB=AC=EB=A0=89=EC=85=98?= =?UTF-8?q?=EC=97=90=20=ED=8F=AC=ED=95=A8=EB=90=9C=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # --- src/document/document.controller.ts | 50 +++++++++++++++++++++++++ src/document/document.service.ts | 58 +++++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/src/document/document.controller.ts b/src/document/document.controller.ts index c5c8326..d9b719d 100644 --- a/src/document/document.controller.ts +++ b/src/document/document.controller.ts @@ -190,6 +190,56 @@ export class DocumentController { return this.documentService.findByTag(uid, tagName, cursor, docId, limit); } + @Get('search/collection') + @ApiQuery({ + name: 'collectionName', + required: true, + type: String, + description: '컬렉션 이름', + example: 'collection0', + }) + @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.', + }) + findByCollection( + @GetUid() uid: string, + @Query('collectionName') collectionName: string, + @Query('cursor') cursor?: Date, + @Query( + 'doc-id', + new DefaultValuePipe('ffffffff-ffff-ffff-ffff-ffffffffffff'), + ) + docId?: string, + @Query('limit', new DefaultValuePipe(20), ParseIntPipe) limit?: number, + ): Promise { + return this.documentService.findByCollection( + uid, + collectionName, + cursor, + docId, + limit, + ); + } + @Delete(':docId') deleteOne( @GetUid() uid: string, diff --git a/src/document/document.service.ts b/src/document/document.service.ts index c6ff1ab..61605d5 100644 --- a/src/document/document.service.ts +++ b/src/document/document.service.ts @@ -349,10 +349,12 @@ export class DocumentService { const user = await this.userService.findByUid(uid); - const tag = await this.prisma.tag.findFirst({ + const tag = await this.prisma.tag.findUnique({ where: { - user: { id: user.id }, - name: tagName, + name_userId: { + name: tagName, + userId: user.id, + }, }, }); @@ -385,6 +387,56 @@ export class DocumentService { return documents.map((document) => new DocumentDto(document)); } + async findByCollection( + uid: string, + collectionName: string, + cursor: Date, + docId: string, + take: number, + ): Promise { + cursor = cursor || new Date(); + take = Math.min(take, 20); + + const user = await this.userService.findByUid(uid); + + const collection = await this.prisma.collection.findUnique({ + where: { + name_userId: { + name: collectionName, + userId: user.id, + }, + }, + }); + + if (!collection) { + throw new NotFoundException(`Tag with name ${collectionName} not found`); + } + + const documents = await this.prisma.document.findMany({ + where: { + AND: [ + { + collections: { some: { id: collection.id } }, + }, + { + OR: [ + { updatedAt: { lt: cursor } }, + { + updatedAt: cursor, + docId: { lt: docId }, + }, + ], + }, + ], + }, + include: { tags: true }, + orderBy: [{ updatedAt: 'desc' }], + take, + }); + + return documents.map((document) => new DocumentDto(document)); + } + private async getDeleteTags(tagIds: bigint[]): Promise { return tagIds.length === 0 ? []