diff --git a/src/main/java/org/websoso/WSSServer/application/KeywordFindApplication.java b/src/main/java/org/websoso/WSSServer/application/KeywordFindApplication.java new file mode 100644 index 00000000..83e314c9 --- /dev/null +++ b/src/main/java/org/websoso/WSSServer/application/KeywordFindApplication.java @@ -0,0 +1,51 @@ +package org.websoso.WSSServer.application; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.websoso.WSSServer.domain.common.KeywordCategoryName; +import org.websoso.WSSServer.dto.keyword.CategoryGetResponse; +import org.websoso.WSSServer.dto.keyword.KeywordByCategoryGetResponse; +import org.websoso.WSSServer.dto.keyword.KeywordGetResponse; +import org.websoso.WSSServer.dto.keyword.KeywordPopularGetResponse; +import org.websoso.WSSServer.library.domain.Keyword; +import org.websoso.WSSServer.library.service.KeywordService; + +@Service +@RequiredArgsConstructor +public class KeywordFindApplication { + + private final KeywordService keywordService; + + @Transactional(readOnly = true) + public KeywordByCategoryGetResponse searchKeywordByCategory(String query) { + List searchedKeywords = keywordService.searchKeyword(query); + List categories = Arrays.stream(KeywordCategoryName.values()) + .map(category -> CategoryGetResponse.of( + keywordService.getKeywordCategory(category.getLabel()), + sortByCategoryAndOrder(category, searchedKeywords) + )) + .toList(); + return KeywordByCategoryGetResponse.of(categories); + } + + @Transactional(readOnly = true) + public KeywordPopularGetResponse searchPopularKeyword(int size) { + List keywords = keywordService.getPopularKeywords(size).stream() + .map(KeywordGetResponse::of) + .toList(); + return KeywordPopularGetResponse.of(keywords); + } + + private List sortByCategoryAndOrder(KeywordCategoryName categoryName, + List searchedKeywords) { + return searchedKeywords.stream() + .filter(k -> k.getKeywordCategory().getKeywordCategoryName().equals(categoryName.getLabel())) + .sorted(Comparator.comparing(Keyword::getSortOrder)) + .map(KeywordGetResponse::of) + .toList(); + } +} diff --git a/src/main/java/org/websoso/WSSServer/controller/KeywordController.java b/src/main/java/org/websoso/WSSServer/controller/KeywordController.java index 1a4ddfb4..50088b63 100644 --- a/src/main/java/org/websoso/WSSServer/controller/KeywordController.java +++ b/src/main/java/org/websoso/WSSServer/controller/KeywordController.java @@ -8,21 +8,30 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.websoso.WSSServer.application.KeywordFindApplication; import org.websoso.WSSServer.dto.keyword.KeywordByCategoryGetResponse; -import org.websoso.WSSServer.library.service.KeywordService; +import org.websoso.WSSServer.dto.keyword.KeywordPopularGetResponse; @RestController @RequestMapping("/keywords") @RequiredArgsConstructor public class KeywordController { - private final KeywordService keywordService; + private final KeywordFindApplication keywordFindApplication; @GetMapping public ResponseEntity searchKeywordByCategory( @RequestParam(required = false) String query) { return ResponseEntity .status(OK) - .body(keywordService.searchKeywordByCategory(query)); + .body(keywordFindApplication.searchKeywordByCategory(query)); + } + + @GetMapping("/popular") + public ResponseEntity searchPopularKeyword( + @RequestParam(required = false, defaultValue = "7") int size) { + return ResponseEntity + .status(OK) + .body(keywordFindApplication.searchPopularKeyword(size)); } } diff --git a/src/main/java/org/websoso/WSSServer/dto/keyword/KeywordPopularGetResponse.java b/src/main/java/org/websoso/WSSServer/dto/keyword/KeywordPopularGetResponse.java new file mode 100644 index 00000000..c278d4f5 --- /dev/null +++ b/src/main/java/org/websoso/WSSServer/dto/keyword/KeywordPopularGetResponse.java @@ -0,0 +1,15 @@ +package org.websoso.WSSServer.dto.keyword; + +import org.websoso.WSSServer.library.domain.KeywordCategory; + +import java.util.List; + +public record KeywordPopularGetResponse( + List keywords +) { + public static KeywordPopularGetResponse of(List keywords) { + return new KeywordPopularGetResponse( + keywords + ); + } +} diff --git a/src/main/java/org/websoso/WSSServer/library/repository/UserNovelKeywordRepository.java b/src/main/java/org/websoso/WSSServer/library/repository/UserNovelKeywordRepository.java index 56bda1aa..eefa42dd 100644 --- a/src/main/java/org/websoso/WSSServer/library/repository/UserNovelKeywordRepository.java +++ b/src/main/java/org/websoso/WSSServer/library/repository/UserNovelKeywordRepository.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Set; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -17,6 +18,9 @@ public interface UserNovelKeywordRepository extends JpaRepository findAllByUserNovel_Novel(Novel novel); + @Query("SELECT unk.keyword FROM UserNovelKeyword unk GROUP BY unk.keyword ORDER BY COUNT(unk) DESC") + List findTopKeywordsByCount(Pageable pageable); + @Modifying(clearAutomatically = true, flushAutomatically = true) @Transactional @Query("DELETE FROM UserNovelKeyword un WHERE un.userNovel = :userNovel AND un.keyword IN :keywords") diff --git a/src/main/java/org/websoso/WSSServer/library/service/KeywordService.java b/src/main/java/org/websoso/WSSServer/library/service/KeywordService.java index a103a7dd..d326b53b 100644 --- a/src/main/java/org/websoso/WSSServer/library/service/KeywordService.java +++ b/src/main/java/org/websoso/WSSServer/library/service/KeywordService.java @@ -3,22 +3,17 @@ import static org.websoso.WSSServer.exception.error.CustomKeywordCategoryError.KEYWORD_CATEGORY_NOT_FOUND; import static org.websoso.WSSServer.exception.error.CustomKeywordError.KEYWORD_NOT_FOUND; -import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.springframework.data.domain.PageRequest; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.websoso.WSSServer.dto.keyword.KeywordCountGetResponse; import org.websoso.WSSServer.library.domain.Keyword; import org.websoso.WSSServer.library.domain.KeywordCategory; -import org.websoso.WSSServer.domain.common.KeywordCategoryName; -import org.websoso.WSSServer.dto.keyword.CategoryGetResponse; -import org.websoso.WSSServer.dto.keyword.KeywordByCategoryGetResponse; -import org.websoso.WSSServer.dto.keyword.KeywordGetResponse; import org.websoso.WSSServer.exception.exception.CustomKeywordCategoryException; import org.websoso.WSSServer.exception.exception.CustomKeywordException; import org.websoso.WSSServer.library.domain.UserNovel; @@ -46,18 +41,6 @@ public Keyword getKeywordOrException(Integer keywordId) { "keyword with the given id is not found")); } - @Transactional(readOnly = true) - public KeywordByCategoryGetResponse searchKeywordByCategory(String query) { - List searchedKeywords = searchKeyword(query); - List categories = Arrays.stream(KeywordCategoryName.values()) - .map(category -> CategoryGetResponse.of( - getKeywordCategory(category.getLabel()), - sortByCategoryAndOrder(category, searchedKeywords) - )) - .toList(); - return KeywordByCategoryGetResponse.of(categories); - } - public void createNovelKeyword(UserNovel userNovel, Keyword keyword) { userNovelKeywordRepository.save(UserNovelKeyword.create(userNovel, keyword)); } @@ -73,22 +56,18 @@ public void deleteUserNovelKeywords(List userNovelKeywords) { userNovelKeywordRepository.deleteAll(userNovelKeywords); } - private KeywordCategory getKeywordCategory(String keywordCategoryName) { + public KeywordCategory getKeywordCategory(String keywordCategoryName) { return keywordCategoryRepository.findByKeywordCategoryName(keywordCategoryName).orElseThrow( () -> new CustomKeywordCategoryException(KEYWORD_CATEGORY_NOT_FOUND, "keyword category with the given name is not found")); } - private List sortByCategoryAndOrder(KeywordCategoryName categoryName, - List searchedKeywords) { - return searchedKeywords.stream() - .filter(k -> k.getKeywordCategory().getKeywordCategoryName().equals(categoryName.getLabel())) - .sorted(Comparator.comparing(Keyword::getSortOrder)) - .map(KeywordGetResponse::of) - .toList(); + @Transactional(readOnly = true) + public List getPopularKeywords(int size) { + return userNovelKeywordRepository.findTopKeywordsByCount(PageRequest.of(0, size)); } - private List searchKeyword(String query) { + public List searchKeyword(String query) { List allKeywords = keywordRepository.findAllByOrderBySortOrderAsc(); if (query == null || query.isBlank()) {