From 6f0b7a8931356ca9ab0e733fe0988a5996dcafea Mon Sep 17 00:00:00 2001 From: Minseong Park <52368015+pminsung12@users.noreply.github.com> Date: Sun, 10 Dec 2023 14:00:34 +0900 Subject: [PATCH] =?UTF-8?q?[Server]=20ai=EC=99=80=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=ED=95=9C=20db=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20(#22?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 경로 이름 수정 entity->entities * feat: category 엔티티 생성 * feat: reason 모델 생성 및 각 테이블 relation 설정 * feat: 각 테이블 relation 수정 및 의존성 주입 * feat: relation 방식 변경으로 인한folders.service.ts 메서드 수정, 의존성 주입 --- server/src/app.module.ts | 8 +++- server/src/categories/categories.module.ts | 4 ++ .../categories/entities/category.entity.ts | 17 ++++++++ .../src/checklist-ai/checklist-ai.module.ts | 11 ++++- .../ai-checklist-item-naver-reason.entity.ts | 21 +++++++++ .../entities/ai-checklist-item.ts | 43 +++++++++++++++++++ .../entities/checklist-ai.entity.ts | 17 -------- .../{entity => entities}/base.entity.ts | 0 .../src/common/entities/checklist.entity.ts | 12 ++++++ server/src/common/entity/checklist.entity.ts | 17 -------- .../feeds/{entity => entities}/feed.entity.ts | 0 server/src/feeds/feeds.module.ts | 5 ++- server/src/feeds/feeds.service.spec.ts | 2 +- server/src/feeds/feeds.service.ts | 24 +++++++++-- server/src/folders/entities/folder.entity.ts | 2 +- .../entities/private-checklist.entity.ts | 2 +- .../entities/shared-checklist-item.entity.ts | 2 +- .../entities/shared-checklist.entity.ts | 2 +- server/src/users/entities/user.entity.ts | 2 +- 19 files changed, 143 insertions(+), 48 deletions(-) create mode 100644 server/src/categories/entities/category.entity.ts create mode 100644 server/src/checklist-ai/entities/ai-checklist-item-naver-reason.entity.ts create mode 100644 server/src/checklist-ai/entities/ai-checklist-item.ts delete mode 100644 server/src/checklist-ai/entities/checklist-ai.entity.ts rename server/src/common/{entity => entities}/base.entity.ts (100%) create mode 100644 server/src/common/entities/checklist.entity.ts delete mode 100644 server/src/common/entity/checklist.entity.ts rename server/src/feeds/{entity => entities}/feed.entity.ts (100%) diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 8eb00b14..580b3c6d 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -18,7 +18,7 @@ import { ChecklistAiModule } from './checklist-ai/checklist-ai.module'; import { CommonModule } from './common/common.module'; import { LoggingInterceptor } from './common/interceptor/log.interceptor'; import { LoggerMiddleware } from './common/middlewares/logger.middleware'; -import { FeedModel } from './feeds/entity/feed.entity'; +import { FeedModel } from './feeds/entities/feed.entity'; import { FeedsModule } from './feeds/feeds.module'; import { FolderModel } from './folders/entities/folder.entity'; import { FoldersModule } from './folders/folders.module'; @@ -30,6 +30,9 @@ import { SharedChecklistsModule } from './shared-checklists/shared-checklists.mo import { UserModel } from './users/entities/user.entity'; import { UsersModule } from './users/users.module'; import { winstonConfig } from './utils/winston.config'; +import { CategoryModel } from './categories/entities/category.entity'; +import { AiChecklistItemModel } from './checklist-ai/entities/ai-checklist-item'; +import { AiChecklistItemNaverReasonModel } from './checklist-ai/entities/ai-checklist-item-naver-reason.entity'; @Module({ imports: [ @@ -52,6 +55,9 @@ import { winstonConfig } from './utils/winston.config'; SharedChecklistModel, SharedChecklistItemModel, FeedModel, + CategoryModel, + AiChecklistItemModel, + AiChecklistItemNaverReasonModel, ], synchronize: true, // DO NOT USE IN PRODUCTION }), diff --git a/server/src/categories/categories.module.ts b/server/src/categories/categories.module.ts index 3499b76a..b4a097e8 100644 --- a/server/src/categories/categories.module.ts +++ b/server/src/categories/categories.module.ts @@ -1,9 +1,13 @@ import { Module } from '@nestjs/common'; import { CategoriesService } from './categories.service'; import { CategoriesController } from './categories.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { CategoryModel } from './entities/category.entity'; @Module({ + imports: [TypeOrmModule.forFeature([CategoryModel])], controllers: [CategoriesController], providers: [CategoriesService], + exports: [TypeOrmModule], }) export class CategoriesModule {} diff --git a/server/src/categories/entities/category.entity.ts b/server/src/categories/entities/category.entity.ts new file mode 100644 index 00000000..bb5800c2 --- /dev/null +++ b/server/src/categories/entities/category.entity.ts @@ -0,0 +1,17 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { BaseModel } from '../../common/entities/base.entity'; + +@Entity() +export class CategoryModel extends BaseModel { + @PrimaryGeneratedColumn() + categoryId: number; + + @Column() + mainCategory: string; + + @Column() + subCategory: string; + + @Column() + minorCategory: string; +} diff --git a/server/src/checklist-ai/checklist-ai.module.ts b/server/src/checklist-ai/checklist-ai.module.ts index 0e1680aa..df1c5f32 100644 --- a/server/src/checklist-ai/checklist-ai.module.ts +++ b/server/src/checklist-ai/checklist-ai.module.ts @@ -2,9 +2,18 @@ import { Module } from '@nestjs/common'; import { ChecklistAiService } from './checklist-ai.service'; import { ChecklistAiController } from './checklist-ai.controller'; import { HttpModule } from '@nestjs/axios'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AiChecklistItemModel } from './entities/ai-checklist-item'; +import { AiChecklistItemNaverReasonModel } from './entities/ai-checklist-item-naver-reason.entity'; @Module({ - imports: [HttpModule], + imports: [ + HttpModule, + TypeOrmModule.forFeature([ + AiChecklistItemModel, + AiChecklistItemNaverReasonModel, + ]), + ], controllers: [ChecklistAiController], providers: [ChecklistAiService], }) diff --git a/server/src/checklist-ai/entities/ai-checklist-item-naver-reason.entity.ts b/server/src/checklist-ai/entities/ai-checklist-item-naver-reason.entity.ts new file mode 100644 index 00000000..e8ccadd4 --- /dev/null +++ b/server/src/checklist-ai/entities/ai-checklist-item-naver-reason.entity.ts @@ -0,0 +1,21 @@ +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; +import { BaseModel } from '../../common/entities/base.entity'; +import { AiChecklistItemModel } from './ai-checklist-item'; + +@Entity() +export class AiChecklistItemNaverReasonModel extends BaseModel { + @PrimaryGeneratedColumn() + aiChecklistItemNaverReasonid: number; + + @Column() + reason: string; + + @ManyToOne( + () => AiChecklistItemModel, + (aiChecklistItem) => aiChecklistItem.reasons, + { + nullable: false, + }, + ) + aiChecklistItem: AiChecklistItemModel; +} diff --git a/server/src/checklist-ai/entities/ai-checklist-item.ts b/server/src/checklist-ai/entities/ai-checklist-item.ts new file mode 100644 index 00000000..8a0457f6 --- /dev/null +++ b/server/src/checklist-ai/entities/ai-checklist-item.ts @@ -0,0 +1,43 @@ +import { + Column, + Entity, + JoinColumn, + ManyToOne, + OneToMany, + PrimaryGeneratedColumn, +} from 'typeorm'; +import { AiChecklistItemNaverReasonModel } from './ai-checklist-item-naver-reason.entity'; +import { BaseModel } from '../../common/entities/base.entity'; +import { CategoryModel } from '../../categories/entities/category.entity'; + +@Entity() +export class AiChecklistItemModel extends BaseModel { + @PrimaryGeneratedColumn() + aiChecklistItemId: number; + + @Column() + content: string; + + @Column({ default: 0 }) + selected_count_by_user: number; + + @Column({ default: 0 }) + selected_count_by_naver_ai: number; + + @Column({ default: 0 }) + evaluated_count_by_naver_ai: number; + + // final_score는 user_selected_count + naver_ai_selected_count + naver_ai_evaluate_count + @Column({ default: 0 }) + final_score: number; + + @ManyToOne(() => CategoryModel) + @JoinColumn({ name: 'categoryId' }) + category: CategoryModel; + + @OneToMany( + () => AiChecklistItemNaverReasonModel, + (reason) => reason.aiChecklistItem, + ) + reasons: AiChecklistItemNaverReasonModel[]; +} diff --git a/server/src/checklist-ai/entities/checklist-ai.entity.ts b/server/src/checklist-ai/entities/checklist-ai.entity.ts deleted file mode 100644 index d5bf158e..00000000 --- a/server/src/checklist-ai/entities/checklist-ai.entity.ts +++ /dev/null @@ -1,17 +0,0 @@ -// import { Column, Entity } from 'typeorm'; -// import { BaseModel } from '../../common/entity/base.entity'; -// -// @Entity() -// export class ChecklistAiEntity extends BaseModel { -// @Column() -// mainCategory: string; -// -// @Column() -// subCategory: string; -// -// @Column() -// minorCategory: string; -// -// @Column() -// selectedCount: number; -// } diff --git a/server/src/common/entity/base.entity.ts b/server/src/common/entities/base.entity.ts similarity index 100% rename from server/src/common/entity/base.entity.ts rename to server/src/common/entities/base.entity.ts diff --git a/server/src/common/entities/checklist.entity.ts b/server/src/common/entities/checklist.entity.ts new file mode 100644 index 00000000..c2fcb876 --- /dev/null +++ b/server/src/common/entities/checklist.entity.ts @@ -0,0 +1,12 @@ +import { BaseModel } from './base.entity'; +import { Column, JoinColumn, ManyToOne } from 'typeorm'; +import { CategoryModel } from '../../categories/entities/category.entity'; + +export abstract class ChecklistModel extends BaseModel { + @Column() + title: string; + + @ManyToOne(() => CategoryModel) + @JoinColumn({ name: 'categoryId' }) + category: CategoryModel; +} diff --git a/server/src/common/entity/checklist.entity.ts b/server/src/common/entity/checklist.entity.ts deleted file mode 100644 index ae986f30..00000000 --- a/server/src/common/entity/checklist.entity.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { BaseModel } from './base.entity'; -// import { IsNumber } from 'class-validator'; -import { Column } from 'typeorm'; - -export abstract class ChecklistModel extends BaseModel { - @Column() - title: string; - - @Column({ nullable: true }) - mainCategory: string; - - @Column({ nullable: true }) - subCategory: string; - - @Column({ nullable: true }) - minorCategory: string; -} diff --git a/server/src/feeds/entity/feed.entity.ts b/server/src/feeds/entities/feed.entity.ts similarity index 100% rename from server/src/feeds/entity/feed.entity.ts rename to server/src/feeds/entities/feed.entity.ts diff --git a/server/src/feeds/feeds.module.ts b/server/src/feeds/feeds.module.ts index dc1c0108..4fda11b3 100644 --- a/server/src/feeds/feeds.module.ts +++ b/server/src/feeds/feeds.module.ts @@ -2,10 +2,11 @@ import { Module } from '@nestjs/common'; import { FeedsService } from './feeds.service'; import { FeedsController } from './feeds.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { FeedModel } from './entity/feed.entity'; +import { FeedModel } from './entities/feed.entity'; +import { CategoriesModule } from '../categories/categories.module'; @Module({ - imports: [TypeOrmModule.forFeature([FeedModel])], + imports: [TypeOrmModule.forFeature([FeedModel]), CategoriesModule], controllers: [FeedsController], providers: [FeedsService], }) diff --git a/server/src/feeds/feeds.service.spec.ts b/server/src/feeds/feeds.service.spec.ts index 9c99b8c3..1f690854 100644 --- a/server/src/feeds/feeds.service.spec.ts +++ b/server/src/feeds/feeds.service.spec.ts @@ -2,7 +2,7 @@ import { BadRequestException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { FeedModel } from './entity/feed.entity'; +import { FeedModel } from './entities/feed.entity'; import { FeedsService } from './feeds.service'; type MockRepository = Partial, jest.Mock>>; diff --git a/server/src/feeds/feeds.service.ts b/server/src/feeds/feeds.service.ts index a8fd6024..30d15320 100644 --- a/server/src/feeds/feeds.service.ts +++ b/server/src/feeds/feeds.service.ts @@ -1,13 +1,16 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { FeedModel } from './entity/feed.entity'; +import { FeedModel } from './entities/feed.entity'; import { Repository } from 'typeorm'; +import { CategoryModel } from '../categories/entities/category.entity'; @Injectable() export class FeedsService { constructor( @InjectRepository(FeedModel) private readonly repository: Repository, + @InjectRepository(CategoryModel) + private readonly categoryRepository: Repository, ) {} async findFeedById(feedId: number) { @@ -21,13 +24,26 @@ export class FeedsService { } async findAllFeedsByCategory(mainCategory: string) { - const feed = await this.repository.find({ where: { mainCategory } }); - if (feed.length === 0) { + // mainCategory를 사용하여 CategoryModel 찾기 + const category = await this.categoryRepository.findOne({ + where: { mainCategory }, + }); + if (!category) { + throw new BadRequestException( + `${mainCategory}는 존재하지 않는 카테고리입니다.`, + ); + } + + // 해당 카테고리 ID를 가진 모든 피드 검색 + const feeds = await this.repository.find({ + where: { category: category }, + }); + if (feeds.length === 0) { throw new BadRequestException( `${mainCategory}에 대한 피드가 존재하지 않습니다.`, ); } - return feed; + return feeds; } async updateLikeCount(feedId: number) { diff --git a/server/src/folders/entities/folder.entity.ts b/server/src/folders/entities/folder.entity.ts index 5c02f464..b826afff 100644 --- a/server/src/folders/entities/folder.entity.ts +++ b/server/src/folders/entities/folder.entity.ts @@ -5,7 +5,7 @@ import { OneToMany, PrimaryGeneratedColumn, } from 'typeorm'; -import { BaseModel } from '../../common/entity/base.entity'; +import { BaseModel } from '../../common/entities/base.entity'; import { UserModel } from '../../users/entities/user.entity'; import { PrivateChecklistModel } from '../private-checklists/entities/private-checklist.entity'; diff --git a/server/src/folders/private-checklists/entities/private-checklist.entity.ts b/server/src/folders/private-checklists/entities/private-checklist.entity.ts index 1f0c2d89..819a31cf 100644 --- a/server/src/folders/private-checklists/entities/private-checklist.entity.ts +++ b/server/src/folders/private-checklists/entities/private-checklist.entity.ts @@ -1,6 +1,6 @@ import { IsBoolean, IsString } from 'class-validator'; import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; -import { ChecklistModel } from '../../../common/entity/checklist.entity'; +import { ChecklistModel } from '../../../common/entities/checklist.entity'; import { UserModel } from '../../../users/entities/user.entity'; import { FolderModel } from '../../entities/folder.entity'; diff --git a/server/src/shared-checklists/entities/shared-checklist-item.entity.ts b/server/src/shared-checklists/entities/shared-checklist-item.entity.ts index 3228eabb..ec68274f 100644 --- a/server/src/shared-checklists/entities/shared-checklist-item.entity.ts +++ b/server/src/shared-checklists/entities/shared-checklist-item.entity.ts @@ -1,4 +1,4 @@ -import { BaseModel } from 'src/common/entity/base.entity'; +import { BaseModel } from 'src/common/entities/base.entity'; import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { SharedChecklistModel } from './shared-checklist.entity'; diff --git a/server/src/shared-checklists/entities/shared-checklist.entity.ts b/server/src/shared-checklists/entities/shared-checklist.entity.ts index 6833ac9a..779ab384 100644 --- a/server/src/shared-checklists/entities/shared-checklist.entity.ts +++ b/server/src/shared-checklists/entities/shared-checklist.entity.ts @@ -5,7 +5,7 @@ import { OneToMany, PrimaryColumn, } from 'typeorm'; -import { ChecklistModel } from '../../common/entity/checklist.entity'; +import { ChecklistModel } from '../../common/entities/checklist.entity'; import { UserModel } from '../../users/entities/user.entity'; import { SharedChecklistItemModel } from './shared-checklist-item.entity'; diff --git a/server/src/users/entities/user.entity.ts b/server/src/users/entities/user.entity.ts index b4d43da2..a8d109d4 100644 --- a/server/src/users/entities/user.entity.ts +++ b/server/src/users/entities/user.entity.ts @@ -1,4 +1,4 @@ -import { BaseModel } from 'src/common/entity/base.entity'; +import { BaseModel } from 'src/common/entities/base.entity'; import { Column, Entity,