From 8f4f3d18caf792b597b84c348c9d43c2674926cc Mon Sep 17 00:00:00 2001 From: niamu01 Date: Fri, 5 Apr 2024 16:46:09 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20:sparkles:=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EC=8B=9C=20feed=20db=20=EC=97=90=EC=84=9C=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #416 --- app/src/feed/feed.module.ts | 44 +++++++++------- app/src/feed/feed.service.ts | 71 ++++++++++++-------------- app/src/follow/follow.cache.service.ts | 3 +- app/src/follow/follow.service.ts | 7 +-- 4 files changed, 61 insertions(+), 64 deletions(-) diff --git a/app/src/feed/feed.module.ts b/app/src/feed/feed.module.ts index b37c6a2b..d6e74cc0 100644 --- a/app/src/feed/feed.module.ts +++ b/app/src/feed/feed.module.ts @@ -1,31 +1,37 @@ import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; +import { FollowCacheService } from 'src/follow/follow.cache.service'; import { PaginationCursorService } from 'src/pagination/cursor/pagination.cursor.service'; -import { - FeedSchema, - FollowFeedSchema, - LocationFeedSchema, - feed, -} from './db/feed.database.schema'; -import { FeedType } from './dto/feed.dto'; +import { FeedSchema, feed } from './db/feed.database.schema'; import { FeedResolver } from './feed.resolver'; import { FeedService } from './feed.service'; @Module({ + //imports: [ + // MongooseModule.forFeature([ + // { + // name: feed.name, + // schema: FeedSchema, + // discriminators: [ + // { name: followFeed.name, schema: FollowFeedSchema }, + // { name: locationFeed.name, schema: LocationFeedSchema }, + // ], + // }, + // ]), + //], imports: [ - MongooseModule.forFeature([ - { - name: feed.name, - schema: FeedSchema, - discriminators: [ - { name: FeedType.FOLLOW, schema: FollowFeedSchema }, - { name: FeedType.LOCATION, schema: LocationFeedSchema }, - ], - }, - ]), + MongooseModule.forFeature([{ name: feed.name, schema: FeedSchema }]), + ], + providers: [ + FeedResolver, + FeedService, + PaginationCursorService, + FollowCacheService, + ], + exports: [ + FeedService, + MongooseModule.forFeature([{ name: feed.name, schema: FeedSchema }]), ], - providers: [FeedResolver, FeedService, PaginationCursorService], //, FeedCacheService], - exports: [FeedService], }) // eslint-disable-next-line diff --git a/app/src/feed/feed.service.ts b/app/src/feed/feed.service.ts index 94b33c88..3abacc28 100644 --- a/app/src/feed/feed.service.ts +++ b/app/src/feed/feed.service.ts @@ -1,15 +1,22 @@ import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/mongoose'; +import { Model } from 'mongoose'; +import { FollowCacheService } from 'src/follow/follow.cache.service'; import { PaginationCursorArgs } from 'src/pagination/cursor/dtos/pagination.cursor.dto'; import { CursorExtractor, PaginationCursorService, } from 'src/pagination/cursor/pagination.cursor.service'; -import { FeedPaginated, FollowFeed, feedUnion } from './model/feed.model'; +import { feed } from './db/feed.database.schema'; +import { FeedPaginated, feedUnion } from './model/feed.model'; @Injectable() export class FeedService { constructor( + @InjectModel(feed.name) + private readonly feedModel: Model, private readonly paginationCursorService: PaginationCursorService, + private readonly followCacheService: FollowCacheService, ) {} async getFeedPaginated({ @@ -19,20 +26,8 @@ export class FeedService { userId: number; args: PaginationCursorArgs; }): Promise { - //pagination을 위해 함수 분리 - //id만 가진 db를 만들어 매번 로컬피드캐시에서 join하기 <- 캐시작업때 고려 - const followFeeds = await this.getFollowFeeds(userId); + const feeds = await this.getFeeds(userId); - const feeds: (typeof feedUnion)[] = [...followFeeds]; - - //if (!feeds.length) { - // return this.generateEmptyFeed(); - //} - - //sort로 정렬 (최신순 고정) - feeds.sort((a, b) => b.at.getTime() - a.at.getTime()); - - //pagination if (args.after) { const afterIndex = feeds.findIndex( (feed) => cursorExtractor(feed) === args.after, @@ -48,30 +43,31 @@ export class FeedService { ); } - //userId의 피드에 뜰 정보 - async getFollowFeeds(userId: number): Promise { - ////followingList가 팔로우한 사람들 - //followingList.map(async (follow) => { - // const followersFollowing = await this.followCacheService.filterByDate( - // follow.userPreview.id, - // 'following', - // follow.followAt, - // ); + async getFeeds(userId: number): Promise<(typeof feedUnion)[]> { + const followList = await this.followCacheService.get(userId, 'following'); + + const conditions = followList.map((follow) => ({ + 'userPreview.id': follow.userPreview.id, + createdAt: { $gt: follow.followAt }, + })); - // followFeeds.push( - // ...followersFollowing.map((follower) => { - // return { - // id: 1, - // at: follow.followAt, - // userPreview: follow.userPreview, - // type: FeedType.FOLLOW, - // followed: follower.userPreview, - // }; - // }), - // ); - //}); + const feeds = await Promise.all( + conditions.map(async (condition) => { + const aggregate = this.feedModel.aggregate(); - return []; + const feed = await aggregate + .match(condition) + .sort({ createdAt: -1 }) + .project({ + _id: 0, + __v: 0, + }); + + return feed; + }), + ); + + return feeds.reduce((acc, curr) => acc.concat(curr), []); } ////fanout-on-write 방식 @@ -96,9 +92,8 @@ export class FeedService { // false, // cursorExtractor, // ); - //} } const cursorExtractor: CursorExtractor = (doc) => { - return `${doc.id.toString()} + ${doc.at.toISOString()}`; + return `${doc.userPreview.id.toString()} + ${doc.createdAt.toISOString()}`; }; diff --git a/app/src/follow/follow.cache.service.ts b/app/src/follow/follow.cache.service.ts index fbc6180f..ccec3a64 100644 --- a/app/src/follow/follow.cache.service.ts +++ b/app/src/follow/follow.cache.service.ts @@ -38,8 +38,7 @@ export class FollowCacheService { return cachedData; } - //todo: cacheUtilService에 추가? - async filterByDate( + async getByDate( userId: number, type: 'follower' | 'following', time: Date, diff --git a/app/src/follow/follow.service.ts b/app/src/follow/follow.service.ts index 32c363dc..2c7fa720 100644 --- a/app/src/follow/follow.service.ts +++ b/app/src/follow/follow.service.ts @@ -8,10 +8,7 @@ import { QueryArgs, QueryOneArgs, } from 'src/database/mongoose/database.mongoose.query'; -import { - followFeed, - FollowFeedDocument, -} from 'src/feed/db/feed.database.schema'; +import { followFeed } from 'src/feed/db/feed.database.schema'; import { FeedType } from 'src/feed/dto/feed.dto'; import { PaginationIndexService } from 'src/pagination/index/pagination.index.service'; import { follow } from './db/follow.database.schema'; @@ -30,7 +27,7 @@ export class FollowService { @InjectModel(follow.name) private readonly followModel: Model, @InjectModel(followFeed.name) - private readonly followFeedModel: Model, + private readonly followFeedModel: Model, private readonly cursusUserCacheService: CursusUserCacheService, private readonly paginationIndexService: PaginationIndexService, private readonly followCacheService: FollowCacheService,