diff --git a/src/main/java/com/movelog/domain/record/application/KeywordService.java b/src/main/java/com/movelog/domain/record/application/KeywordService.java index ee8b155..84f6eee 100644 --- a/src/main/java/com/movelog/domain/record/application/KeywordService.java +++ b/src/main/java/com/movelog/domain/record/application/KeywordService.java @@ -4,6 +4,7 @@ import com.movelog.domain.record.domain.Record; import com.movelog.domain.record.domain.repository.RecordRepository; import com.movelog.domain.record.dto.response.MyKeywordStatsRes; +import com.movelog.domain.record.dto.response.RecommendKeywordInStatsRes; import com.movelog.domain.record.dto.response.SearchKeywordInStatsRes; import com.movelog.domain.record.exception.KeywordNotFoundException; import com.movelog.domain.record.domain.repository.KeywordRepository; @@ -14,6 +15,7 @@ import com.movelog.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -34,10 +36,11 @@ public class KeywordService { public List searchKeywordInStats(UserPrincipal userPrincipal, String keyword) { - User user = validUserById(userPrincipal); + validUserById(userPrincipal); // 검색어를 포함한 키워드 리스트 조회 - List keywords = keywordRepository.findAllByUserAndKeywordContaining(user, keyword); + List keywords = keywordRepository.findAllKeywordStartingWith(keyword); + log.info("Searching for keywords starting with: {}", keyword); // 기록이 많은 순서대로 정렬 keywords = sortKeywordByRecordCount(keywords); @@ -54,6 +57,10 @@ public List searchKeywordInStats(UserPrincipal userPrin public MyKeywordStatsRes getMyKeywordStatsRes(UserPrincipal userPrincipal, Long keywordId) { validUserById(userPrincipal); Keyword keyword = validKeywordById(keywordId); + // 사용자가 기록한 키워드가 아닐 시, 빈 배열 반환 + if (!keyword.getUser().getId().equals(userPrincipal.getId())) { + return MyKeywordStatsRes.builder().build(); + } return MyKeywordStatsRes.builder() .noun(keyword.getKeyword()) @@ -122,6 +129,18 @@ private double roundToTwoDecimal(double value) { return Math.round(value * 100) / 100.0; } + public List getRecommendKeywords(UserPrincipal userPrincipal) { + User user = validUserById(userPrincipal); + List keywords = keywordRepository.findTop5ByUserOrderByCreatedAtDesc(user); + + return keywords.stream() + .map(keyword -> RecommendKeywordInStatsRes.builder() + .keywordId(keyword.getKeywordId()) + .noun(keyword.getKeyword()) + .build()) + .toList(); + } + private User validUserById(UserPrincipal userPrincipal) { Optional userOptional = userService.findById(userPrincipal.getId()); // Optional userOptional = userRepository.findById(5L); @@ -135,4 +154,5 @@ private Keyword validKeywordById(Long keywordId) { return keywordOptional.get(); } + } diff --git a/src/main/java/com/movelog/domain/record/domain/repository/KeywordRepository.java b/src/main/java/com/movelog/domain/record/domain/repository/KeywordRepository.java index 0ebae04..eb543df 100644 --- a/src/main/java/com/movelog/domain/record/domain/repository/KeywordRepository.java +++ b/src/main/java/com/movelog/domain/record/domain/repository/KeywordRepository.java @@ -5,6 +5,7 @@ import com.movelog.domain.record.domain.VerbType; import com.movelog.domain.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import java.util.List; @@ -21,4 +22,8 @@ public interface KeywordRepository extends JpaRepository { List findAllByUserAndKeywordContaining(User user, String keyword); + @Query("SELECT k FROM Keyword k WHERE LOWER(k.keyword) LIKE LOWER(CONCAT(:keyword, '%'))") + List findAllKeywordStartingWith(String keyword); + + } diff --git a/src/main/java/com/movelog/domain/record/dto/response/RecommendKeywordInStatsRes.java b/src/main/java/com/movelog/domain/record/dto/response/RecommendKeywordInStatsRes.java new file mode 100644 index 0000000..f22783e --- /dev/null +++ b/src/main/java/com/movelog/domain/record/dto/response/RecommendKeywordInStatsRes.java @@ -0,0 +1,19 @@ +package com.movelog.domain.record.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class RecommendKeywordInStatsRes { + @Schema( type = "int", example = "1", description="추천 키워드 ID") + private Long keywordId; + + @Schema( type = "String", example ="헬스", description="추천 키워드(명사)") + private String noun; +} diff --git a/src/main/java/com/movelog/domain/record/presentation/StatsController.java b/src/main/java/com/movelog/domain/record/presentation/StatsController.java index 3c97fe0..d729545 100644 --- a/src/main/java/com/movelog/domain/record/presentation/StatsController.java +++ b/src/main/java/com/movelog/domain/record/presentation/StatsController.java @@ -2,6 +2,7 @@ import com.movelog.domain.record.application.KeywordService; import com.movelog.domain.record.dto.response.MyKeywordStatsRes; +import com.movelog.domain.record.dto.response.RecommendKeywordInStatsRes; import com.movelog.domain.record.dto.response.SearchKeywordInStatsRes; import com.movelog.global.config.security.token.UserPrincipal; import com.movelog.global.payload.ErrorResponse; @@ -64,6 +65,21 @@ public ResponseEntity getMyKeywordStats( return ResponseEntity.ok(response); } + @Operation(summary = "통계 추천 단어 조회 API", description = "사용자가 최근 기록한 단어 목록(최대 5개)을 조회하는 API입니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "통계 추천 단어 조회 성공", + content = @Content(mediaType = "application/json", + schema = @Schema(type = "array", implementation = RecommendKeywordInStatsRes.class))), + @ApiResponse(responseCode = "400", description = "통계 추천 단어 조회 실패", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))) + }) + @GetMapping("/word/recommend") + public ResponseEntity getRecommendKeywords( + @Parameter(description = "Access Token을 입력해주세요.", required = true) @AuthenticationPrincipal UserPrincipal userPrincipal + ) { + List response = keywordService.getRecommendKeywords(userPrincipal); + return ResponseEntity.ok(response); + } }