From d76aac8c77e3db2cf3b2030aed663654f5ad5486 Mon Sep 17 00:00:00 2001 From: dhkstnaos Date: Thu, 1 Dec 2022 20:57:28 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question/QuestionSearchController.java | 30 +++++++++++++++++++ .../application/QuestionSearchService.java | 0 2 files changed, 30 insertions(+) create mode 100644 src/main/java/com/developer/wiki/question/presentation/question/QuestionSearchController.java create mode 100644 src/main/java/com/developer/wiki/question/query/application/QuestionSearchService.java diff --git a/src/main/java/com/developer/wiki/question/presentation/question/QuestionSearchController.java b/src/main/java/com/developer/wiki/question/presentation/question/QuestionSearchController.java new file mode 100644 index 0000000..fecd740 --- /dev/null +++ b/src/main/java/com/developer/wiki/question/presentation/question/QuestionSearchController.java @@ -0,0 +1,30 @@ +package com.developer.wiki.question.presentation.question; + +import com.developer.wiki.oauth.User; +import com.developer.wiki.question.query.application.QuestionSearchService; +import com.developer.wiki.question.query.application.SummaryQuestionResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/questions") +@RequiredArgsConstructor +public class QuestionSearchController { + + private final QuestionSearchService questionSearchService; + + @GetMapping("/search") + public ResponseEntity> getSlice( + @AuthenticationPrincipal User currentUser, @RequestParam String keyword, Pageable pageable) { + Slice summarySlice = questionSearchService.findPage(pageable, + currentUser, keyword); + return ResponseEntity.ok(summarySlice); + } +} diff --git a/src/main/java/com/developer/wiki/question/query/application/QuestionSearchService.java b/src/main/java/com/developer/wiki/question/query/application/QuestionSearchService.java new file mode 100644 index 0000000..e69de29 From 7df262753aaa09fbc77eeeffd77e709521ee4d7e Mon Sep 17 00:00:00 2001 From: dhkstnaos Date: Thu, 1 Dec 2022 20:57:37 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EC=84=9C=EB=B9=84=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/QuestionSearchService.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/com/developer/wiki/question/query/application/QuestionSearchService.java b/src/main/java/com/developer/wiki/question/query/application/QuestionSearchService.java index e69de29..be0bab2 100644 --- a/src/main/java/com/developer/wiki/question/query/application/QuestionSearchService.java +++ b/src/main/java/com/developer/wiki/question/query/application/QuestionSearchService.java @@ -0,0 +1,24 @@ +package com.developer.wiki.question.query.application; + +import com.developer.wiki.oauth.User; +import com.developer.wiki.question.command.domain.QuestionSearchRepository; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class QuestionSearchService { + + private final QuestionSearchRepository questionSearchRepository; + + public Slice findPage(Pageable pageable, + User currentUser, String keyword) { + Long userId = Objects.isNull(currentUser) ? null : currentUser.getId(); + return questionSearchRepository.findPageByUserIdAndKeyword(pageable, userId, keyword); + } +} From 0cbc0733580ceb9c69654fb0a5e4515b97717a34 Mon Sep 17 00:00:00 2001 From: dhkstnaos Date: Thu, 1 Dec 2022 20:57:53 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question/command/domain/QuestionSearchRepository.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/developer/wiki/question/command/domain/QuestionSearchRepository.java b/src/main/java/com/developer/wiki/question/command/domain/QuestionSearchRepository.java index 7b9b37b..ac24560 100644 --- a/src/main/java/com/developer/wiki/question/command/domain/QuestionSearchRepository.java +++ b/src/main/java/com/developer/wiki/question/command/domain/QuestionSearchRepository.java @@ -1,12 +1,11 @@ package com.developer.wiki.question.command.domain; import com.developer.wiki.question.query.application.SummaryQuestionResponse; +import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import java.util.List; - public interface QuestionSearchRepository { Page findPageByUserId(Pageable pageable, String mainCategory, List subCategory, @@ -16,4 +15,6 @@ Page findBookmarkByUserId(Pageable pageable, String mai Long userId); Slice findRandomBy(Pageable pageable, String mainCategory, List subCategory); + + Page findPageByUserIdAndKeyword(Pageable pageable, Long userId, String keyword); } From e4cd7071c93dfb7d74dd69716a34838a2a848435 Mon Sep 17 00:00:00 2001 From: dhkstnaos Date: Thu, 1 Dec 2022 20:58:02 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/QuestionSearchRepositoryImpl.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/developer/wiki/question/infra/QuestionSearchRepositoryImpl.java b/src/main/java/com/developer/wiki/question/infra/QuestionSearchRepositoryImpl.java index ab14cab..375dd1f 100644 --- a/src/main/java/com/developer/wiki/question/infra/QuestionSearchRepositoryImpl.java +++ b/src/main/java/com/developer/wiki/question/infra/QuestionSearchRepositoryImpl.java @@ -86,6 +86,23 @@ public Slice findRandomBy(Pageable pageable, String mainCategory, return new SliceImpl<>(courses, pageable, hasNext); } + @Override + public Page findPageByUserIdAndKeyword(Pageable pageable, Long userId, + String keyword) { + List questions = jpaQueryFactory.select(question).from(question) + .leftJoin(question.bookmarks) + .where(keywordListContains(keyword), question.isApproved.isTrue()) + .orderBy(question.id.asc()).offset(pageable.getOffset()).limit(pageable.getPageSize()) + .distinct().fetch(); + List summaryQuestionResponses = questions.stream().map(question -> { + Boolean isBookmarked = exist(question.getId(), userId); + return new SummaryQuestionResponse(question.getId(), question.getTitle(), + question.getMainCategory(), question.getSubCategory(), question.getViewCount(), + question.getCommentCount(), question.getCreatedAt(), isBookmarked); + }).collect(Collectors.toList()); + return new PageImpl<>(summaryQuestionResponses, pageable, questions.size()); + } + private BooleanExpression mainCategoryEq(String mainCategory) { return ObjectUtils.isEmpty(mainCategory) ? null : question.mainCategory.eq(MainCategory.of(mainCategory)); @@ -112,7 +129,7 @@ private BooleanExpression userIdEq(Long userId) { return Objects.isNull(userId) ? null : bookmark.userId.eq(userId); } - public Boolean exist(Long questionId, Long userId) { + private Boolean exist(Long questionId, Long userId) { if (userId == null) { userId = 0L; } @@ -123,4 +140,17 @@ public Boolean exist(Long questionId, Long userId) { } + private BooleanBuilder keywordListContains(String keyword) { + if (ObjectUtils.isEmpty(keyword)) { + return null; + } + BooleanBuilder builder = new BooleanBuilder(); + String[] splitedKeyword = keyword.split(" "); + for (String value : splitedKeyword) { + builder.or(question.title.contains(value)); + builder.or(question.tailQuestions.any().tailQuestion.contains(value)); + } + return builder; + } + }