Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat #51] 질문 검색 결과에 북마크 수, 추천 수 추가 #52

Merged
merged 12 commits into from
Aug 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@
import com.dnd.gongmuin.post_interaction.dto.InteractionResponse;
import com.dnd.gongmuin.post_interaction.service.InteractionService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

@Tag(name = "상호작용 API")
@RestController
@RequiredArgsConstructor
public class InteractionController {

private final InteractionService interactionService;

@Operation(summary = "상호작용 등록 API", description = "게시글을 추천하거나 북마크한다.")
@PostMapping("/api/question-posts/{questionPostId}/activated")
public ResponseEntity<InteractionResponse> activateInteraction(
@PathVariable("questionPostId") Long questionPostId,
Expand All @@ -34,6 +38,7 @@ public ResponseEntity<InteractionResponse> activateInteraction(
return ResponseEntity.ok(response);
}

@Operation(summary = "상호작용 등록 API", description = "게시글을 추천하거나 북마크 취소한다.")
@PostMapping("/api/question-posts/{questionPostId}/inactivated")
public ResponseEntity<InteractionResponse> inactivateInteraction(
@PathVariable("questionPostId") Long questionPostId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.dnd.gongmuin.question_post.dto.request.RegisterQuestionPostRequest;
import com.dnd.gongmuin.question_post.dto.response.MemberInfo;
import com.dnd.gongmuin.question_post.dto.response.QuestionPostDetailResponse;
import com.dnd.gongmuin.question_post.dto.response.QuestionPostSimpleResponse;
import com.dnd.gongmuin.question_post.dto.response.RegisterQuestionPostResponse;

import lombok.AccessLevel;
Expand Down Expand Up @@ -45,8 +44,8 @@ public static QuestionPostDetailResponse toQuestionPostDetailResponse(
member.getNickname(),
member.getJobGroup().getLabel()
),
recommendCount,
savedCount,
recommendCount,
questionPost.getCreatedAt().toString()
);
}
Expand All @@ -71,16 +70,4 @@ public static RegisterQuestionPostResponse toQuestionPostDetailResponse(
questionPost.getCreatedAt().toString()
);
}

public static QuestionPostSimpleResponse toQuestionPostSimpleResponse(QuestionPost questionPost) {
return new QuestionPostSimpleResponse(
questionPost.getId(),
questionPost.getTitle(),
questionPost.getContent(),
questionPost.getJobGroup().getLabel(),
questionPost.getReward(),
questionPost.getCreatedAt().toString(),
questionPost.getIsChosen()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public record QuestionPostDetailResponse(
int reward,
String targetJobGroup,
MemberInfo memberInfo,
int recommendCount,
int savedCount,
int recommendCount,
String createdAt
) {
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
package com.dnd.gongmuin.question_post.dto.response;

import com.dnd.gongmuin.question_post.domain.QuestionPost;
import com.querydsl.core.annotations.QueryProjection;

public record QuestionPostSimpleResponse(
Long questionPostId,
String title,
String content,
String jobGroup,
int reward,
String createdAt,
boolean isChosen
// TODO: 8/11/24 북마크 수, 추천수 추가
boolean isChosen,
int savedCount,
int recommendCount
) {

@QueryProjection
public QuestionPostSimpleResponse(
QuestionPost questionPost,
int savedCount,
int recommendCount
) {
this(
questionPost.getId(),
questionPost.getTitle(),
questionPost.getContent(),
questionPost.getJobGroup().getLabel(),
questionPost.getReward(),
questionPost.getCreatedAt().toString(),
questionPost.getIsChosen(),
savedCount,
recommendCount
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

import com.dnd.gongmuin.question_post.domain.QuestionPost;
import com.dnd.gongmuin.question_post.dto.request.QuestionPostSearchCondition;
import com.dnd.gongmuin.question_post.dto.response.QuestionPostSimpleResponse;

public interface QuestionPostQueryRepository {
Slice<QuestionPost> searchQuestionPosts(QuestionPostSearchCondition condition, Pageable pageable);
Slice<QuestionPostSimpleResponse> searchQuestionPosts(QuestionPostSearchCondition condition, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
import org.springframework.stereotype.Repository;

import com.dnd.gongmuin.member.domain.JobGroup;
import com.dnd.gongmuin.question_post.domain.QuestionPost;
import com.dnd.gongmuin.post_interaction.domain.InteractionType;
import com.dnd.gongmuin.post_interaction.domain.QInteractionCount;
import com.dnd.gongmuin.question_post.domain.QQuestionPost;
import com.dnd.gongmuin.question_post.dto.request.QuestionPostSearchCondition;
import com.dnd.gongmuin.question_post.dto.response.QQuestionPostSimpleResponse;
import com.dnd.gongmuin.question_post.dto.response.QuestionPostSimpleResponse;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;

Expand All @@ -24,9 +28,27 @@ public class QuestionPostQueryRepositoryImpl implements QuestionPostQueryReposit
private final JPAQueryFactory queryFactory;

@Override
public Slice<QuestionPost> searchQuestionPosts(QuestionPostSearchCondition condition, Pageable pageable) {
List<QuestionPost> content = queryFactory.select(questionPost)
public Slice<QuestionPostSimpleResponse> searchQuestionPosts(
QuestionPostSearchCondition condition,
Pageable pageable
) {
QQuestionPost questionPost = QQuestionPost.questionPost;
QInteractionCount saved = new QInteractionCount("saved");
QInteractionCount recommend = new QInteractionCount("recommend");

List<QuestionPostSimpleResponse> content = queryFactory
.select(new QQuestionPostSimpleResponse(
questionPost,
saved.count.coalesce(0),
recommend.count.coalesce(0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

삼항 연산자를 쓰는기 불편했는데 coalesce()를 쓰면 null일 때 0으로 반환되군요? 저도 써봐야겠네요!

))
.from(questionPost)
.leftJoin(saved)
.on(questionPost.id.eq(saved.questionPostId)
.and(saved.type.eq(InteractionType.SAVED)))
.leftJoin(recommend)
.on(questionPost.id.eq(recommend.questionPostId)
.and(recommend.type.eq(InteractionType.RECOMMEND)))
.where(
keywordContains(condition.keyword()),
jobGroupContains(condition.jobGroups()),
Expand Down Expand Up @@ -61,7 +83,7 @@ private BooleanExpression keywordContains(String keyword) {
return keyword != null ? questionPost.title.contains(keyword) : null;
}

private boolean hasNext(int pageSize, List<QuestionPost> questionPosts) {
private boolean hasNext(int pageSize, List<QuestionPostSimpleResponse> questionPosts) {
if (questionPosts.size() <= pageSize) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

import com.dnd.gongmuin.question_post.domain.QuestionPost;

public interface QuestionPostRepository extends JpaRepository<QuestionPost, Long> {
public interface QuestionPostRepository extends JpaRepository<QuestionPost, Long>, QuestionPostQueryRepository {
boolean existsById(Long id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.dnd.gongmuin.question_post.dto.response.QuestionPostSimpleResponse;
import com.dnd.gongmuin.question_post.dto.response.RegisterQuestionPostResponse;
import com.dnd.gongmuin.question_post.exception.QuestionPostErrorCode;
import com.dnd.gongmuin.question_post.repository.QuestionPostQueryRepository;
import com.dnd.gongmuin.question_post.repository.QuestionPostRepository;

import lombok.RequiredArgsConstructor;
Expand All @@ -32,7 +31,6 @@
public class QuestionPostService {

private final QuestionPostRepository questionPostRepository;
private final QuestionPostQueryRepository questionPostQueryRepository;

private final InteractionCountRepository interactionCountRepository;

Expand Down Expand Up @@ -66,9 +64,8 @@ public PageResponse<QuestionPostSimpleResponse> searchQuestionPost(
QuestionPostSearchCondition condition,
Pageable pageable
) {
Slice<QuestionPostSimpleResponse> responsePage = questionPostQueryRepository
.searchQuestionPosts(condition, pageable)
.map(QuestionPostMapper::toQuestionPostSimpleResponse);
Slice<QuestionPostSimpleResponse> responsePage = questionPostRepository
.searchQuestionPosts(condition, pageable);
return PageMapper.toPageResponse(responsePage);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,25 @@
public class InteractionCountFixture {

public static InteractionCount interactionCount(
Long id,
InteractionType type,
Long questionPostId
) {
InteractionCount interactionCount = InteractionCount.of(
type,
questionPostId
);
ReflectionTestUtils.setField(interactionCount, "id", 1L);
ReflectionTestUtils.setField(interactionCount, "id", id);
return interactionCount;
}

public static InteractionCount interactionCount(
InteractionType type,
Long questionPostId
) {
return InteractionCount.of(
type,
questionPostId
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
public class InteractionFixture {

public static Interaction interaction(
Long id,
InteractionType type,
Long memberId,
Long questionPostId
Expand All @@ -21,11 +22,23 @@ public static Interaction interaction(
memberId,
questionPostId
);
ReflectionTestUtils.setField(interaction, "id", 1L);
ReflectionTestUtils.setField(interaction, "id", id);
return interaction;
}

public static Interaction interaction2(

public static Interaction interaction(
InteractionType type,
Long memberId,
Long questionPostId
) {
return Interaction.of(
type,
memberId,
questionPostId
);
}

public static Interaction interaction2(
InteractionType type,
Long memberId,
Long questionPostId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ void activateInteraction_update() {
//given
InteractionType type = InteractionType.RECOMMEND;
QuestionPost questionPost = QuestionPostFixture.questionPost(1L, questioner);
Interaction interaction = InteractionFixture.interaction(type, interactor.getId(),
Interaction interaction = InteractionFixture.interaction(1L, type, interactor.getId(),
questionPost.getId());
InteractionCount interactionCount = InteractionCountFixture.interactionCount(type,
InteractionCount interactionCount = InteractionCountFixture.interactionCount(1L, type,
interactor.getId());
interaction.updateIsInteracted(false);
interactionCount.decreaseCount();
Expand Down Expand Up @@ -150,9 +150,9 @@ void inactivateInteraction() {
//given
InteractionType type = InteractionType.RECOMMEND;
QuestionPost questionPost = QuestionPostFixture.questionPost(1L, questioner);
Interaction interaction = InteractionFixture.interaction(type, interactor.getId(),
Interaction interaction = InteractionFixture.interaction(1L, type, interactor.getId(),
questionPost.getId());
InteractionCount interactionCount = InteractionCountFixture.interactionCount(type,
InteractionCount interactionCount = InteractionCountFixture.interactionCount(1L, type,
interactor.getId());

given(interactionRepository.findByQuestionPostIdAndMemberIdAndType(
Expand Down
Loading
Loading