NestJS-Follow count

jaegeunsong97·2024년 2월 23일
0

NestJS

목록 보기
37/37
post-custom-banner

🖊️Follow Count increment & decrement

팔로우를 누른 경우, 팔로우 요청 또는 팔로우 삭제 경우에만 count를 조절하도록 하겠습니다.

트랜젝션을 사용해서 구현을 해보겠습니다. 먼저 count를 담당할 컬럼을 만들겠습니다.

  • users.entity.ts
.
.
@Column({
  	default: 0
})
followerCount: number;

@Column({
  	default: 0
})
followeeCount: number;
  • users.controller.ts
@Patch('follow/:id/confirm') // 나를 팔로우 하려는 상대 id
@UseInterceptors(TransactionInterceptor)
async patchFollowConfirm(
    @User() user: UsersModel,
    @Param('id', ParseIntPipe) followerId: number,
    @QueryRunner() qr: QR,
) {
    await this.usersService.confirmFollow(followerId, user.id, qr);
    await this.usersService.incrementFollowerCount(user.id, qr);
    return true;
}

@Delete('follow/:id')
@UseInterceptors(TransactionInterceptor)
async deleteFollow(
    @User() user: UsersModel,
    @Param('id', ParseIntPipe) followeeId: number, // 내가 팔로우하는 상대
    @QueryRunner() qr: QR,
) {
    await this.usersService.deleteFollow(user.id, followeeId, qr);
    await this.usersService.decrementFollowerCount(user.id, qr);
    return true;
}
  • users.service.ts
getUsersRepository(qr?: QueryRunner) {
  // qr 있는 경우
  return qr ? qr.manager.getRepository<UsersModel>(UsersModel) : this.usersRepository;
}
     
getUsersFollowRepository(qr?: QueryRunner) {
  // qr 있는 경우
  return qr ? qr.manager.getRepository<UserFollowersModel>(UserFollowersModel) : this.userFollowersRepository;
}
.
.
async followUser(followerId: number, followeeId: number, qr?: QueryRunner) {
    const userFollowersRepository = this.getUsersFollowRepository(qr);
    await userFollowersRepository.save({
        follower: {
          	id: followerId
        },
        followee: {
          	id: followeeId
        }
    });

    return true;
}
.
.
async confirmFollow(followerId: number, followeeId: number, qr?: QueryRunner) {
    const userFollowersRepository = this.getUsersFollowRepository(qr);

    // 중간테이블에 데이터가 존재하는지 확인
    const existing = await userFollowersRepository.findOne({
        where: {
            follower: {
              	id: followerId
            },
            followee: {
              	id: followeeId
            }
        },
        relations: {
            follower: true,
            followee: true
        },
    });
    if (!existing) throw new BadRequestException(`존재하지 않는 팔로우 요청입니다. `);

    // save값을 넣으면, 변경된 부분만 update한다.
    await userFollowersRepository.save({
        ...existing,
        isConfirmed: true,
    });
    return true;
}
.
.
async deleteFollow(followerId: number, followeeId: number, qr?: QueryRunner) {
    const userFollowersRepository = this.getUsersFollowRepository(qr);
    await userFollowersRepository.delete({
        follower: {
          	id: followerId,
        },
        followee: {
          	id: followeeId,
        },
    });
    return true;
}
.
.
async incrementFollowerCount(userId: number, qr?: QueryRunner) {
    const userRepository = this.getUsersRepository(qr);
    await userRepository.increment({
      	id: userId
    }, 'followerCount', 1);
}

async decrementFollowerCount(userId: number, qr?: QueryRunner) {
    const userRepository = this.getUsersRepository(qr);
    await userRepository.decrement({
      	id: userId
    }, 'followerCount', 1);
}

테스트를 진행해보겠습니다.

현재 1번 사용자로 2번사용자를 팔로우하고 1번사용자가 요청을 수락하면 2번 사용자의 follwer는 1증가합니다. 하지만 1번 사용자의 follwee는 0 그대로 존재합니다.

이 문제를 해결해보겠습니다.

{{추가 필요!!!!!!!!!!!!!!}}


🖊️Comment Count

  • posts.service.ts
async incrementCommentCount(postId: number, qr?: QueryRunner) {
    const repository = this.getRepository(qr);
    await repository.increment({
      	id: postId,
    }, 'commentCount', 1);
}

async decrementCommentCount(postId: number, qr?: QueryRunner) {
    const repository = this.getRepository(qr);
    await repository.decrement({
      	id: postId,
    }, 'commentCount', 1);
}
  • comments.service.ts
.
.
getRepository(qr?: QueryRunner) {
	return qr ? qr.manager.getRepository<CommentsModel>(CommentsModel) : this.commentsRepository;
}
.
.
async createComment(
    dto: CreateCommentsDto,
    postId: number,
    author: UsersModel,
    qr?: QueryRunner,
) {
    const repository = this.getRepository(qr);
    return repository.save({
        ...dto,
        post: {
          	id: postId
        },
        author,
    });
}
.
.
async deleteComment(
    id: number,
    qr?: QueryRunner
) {
    const repository = this.getRepository(qr);
    const comment = await repository.findOne({
        where: {
          	id,
        }
    });
    if (!comment) throw new BadRequestException(`존재하지 않는 댓글입니다. `);
    await repository.delete(id);
    return id;
}
  • comments.controller.ts
@Post()
@UseInterceptors(TransactionInterceptor)
async postComment(
    @Param('postId', ParseIntPipe) postId: number,
    @Body() body: CreateCommentsDto,
    @User() user: UsersModel,
    @QueryRunner() qr: QR,
) {
    const resp = await this.commentsService.createComment(
        body, 
        postId, 
        user,
        qr
    );
    await this.postsService.incrementCommentCount(
        postId,
        qr
    );

    return resp;
}
.
.
@Delete(':commentId')
@UseInterceptors(TransactionInterceptor)
@UseGuards(IsCommentMineOrAdminGuard)
async deleteComment(
    @Param('commentId', ParseIntPipe) commentId: number,
    @Param('postId', ParseIntPipe) postId: number, // endpoint에서 받아옴
    @QueryRunner() qr: QR,
) {
    const resp = await this.commentsService.deleteComment(
      commentId,
      qr
    );
    await this.postsService.decrementCommentCount(postId, qr);
    return resp;
}
profile
블로그 이전 : https://medium.com/@jaegeunsong97
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 5월 21일

Useful knowledge and worth learning. Enjoy having exciting experiences. Please continue to update and share information sources. Besides, expand and improve your knowledge even more basketbros

답글 달기