diff --git a/src/main/java/in/koreatech/koin/domain/community/article/dto/BusArticleProjection.java b/src/main/java/in/koreatech/koin/domain/community/article/dto/BusArticleProjection.java new file mode 100644 index 0000000000..cb14cb86af --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/community/article/dto/BusArticleProjection.java @@ -0,0 +1,11 @@ +package in.koreatech.koin.domain.community.article.dto; + +import java.time.LocalDateTime; + +public record BusArticleProjection( + Integer id, + String title, + LocalDateTime createdAt +) { + +} diff --git a/src/main/java/in/koreatech/koin/domain/community/article/model/redis/BusNoticeArticle.java b/src/main/java/in/koreatech/koin/domain/community/article/model/redis/BusNoticeArticle.java index 4c3e062d5c..7453fe0e2a 100644 --- a/src/main/java/in/koreatech/koin/domain/community/article/model/redis/BusNoticeArticle.java +++ b/src/main/java/in/koreatech/koin/domain/community/article/model/redis/BusNoticeArticle.java @@ -1,10 +1,10 @@ package in.koreatech.koin.domain.community.article.model.redis; -import in.koreatech.koin.domain.community.article.model.Article; import org.springframework.data.annotation.Id; +import org.springframework.data.redis.core.RedisHash; + import lombok.Builder; import lombok.Getter; -import org.springframework.data.redis.core.RedisHash; @Getter @RedisHash(value = "busNoticeArticle") @@ -21,10 +21,10 @@ private BusNoticeArticle(Integer id, String title) { this.title = title; } - public static BusNoticeArticle from(Article article) { + public static BusNoticeArticle of(int id, String title) { return BusNoticeArticle.builder() - .id(article.getId()) - .title(article.getTitle()) - .build(); + .id(id) + .title(title) + .build(); } } diff --git a/src/main/java/in/koreatech/koin/domain/community/article/repository/ArticleRepository.java b/src/main/java/in/koreatech/koin/domain/community/article/repository/ArticleRepository.java index daabf61dc3..1733dc9973 100644 --- a/src/main/java/in/koreatech/koin/domain/community/article/repository/ArticleRepository.java +++ b/src/main/java/in/koreatech/koin/domain/community/article/repository/ArticleRepository.java @@ -14,6 +14,7 @@ import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.Param; +import in.koreatech.koin.domain.community.article.dto.BusArticleProjection; import in.koreatech.koin.domain.community.article.exception.ArticleNotFoundException; import in.koreatech.koin.domain.community.article.exception.BoardNotFoundException; import in.koreatech.koin.domain.community.article.model.Article; @@ -184,8 +185,19 @@ List
findAllByRegisteredAtIsAfterExcludingBoardId(@Param("registeredAt" @Query("SELECT a.title FROM Article a WHERE a.id = :id") String getTitleById(@Param("id") Integer id); - @Query(value = "SELECT * FROM new_articles a " - + "WHERE a.title REGEXP '통학버스|등교버스|셔틀버스|하교버스' AND a.is_notice = true " - + "ORDER BY a.created_at DESC LIMIT 5", nativeQuery = true) - List
findBusArticlesTop5OrderByCreatedAtDesc(); + @Query(""" + SELECT new in.koreatech.koin.domain.community.article.dto.BusArticleProjection( + a.id, a.title, a.createdAt + ) + FROM Article a + WHERE ( + a.title LIKE '%통학버스%' + OR a.title LIKE '%등교버스%' + OR a.title LIKE '%셔틀버스%' + OR a.title LIKE '%하교버스%' + ) + AND a.isNotice = true + ORDER BY a.createdAt DESC + """) + List findBusArticlesTop5OrderByCreatedAtDesc(Pageable pageable); } diff --git a/src/main/java/in/koreatech/koin/domain/community/article/service/ArticleSyncService.java b/src/main/java/in/koreatech/koin/domain/community/article/service/ArticleSyncService.java index 28ebcf226d..f4422c2e03 100644 --- a/src/main/java/in/koreatech/koin/domain/community/article/service/ArticleSyncService.java +++ b/src/main/java/in/koreatech/koin/domain/community/article/service/ArticleSyncService.java @@ -1,5 +1,21 @@ package in.koreatech.koin.domain.community.article.service; +import java.time.Clock; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ZSetOperations.TypedTuple; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import in.koreatech.koin.domain.community.article.dto.BusArticleProjection; import in.koreatech.koin.domain.community.article.model.Article; import in.koreatech.koin.domain.community.article.model.ArticleSearchKeyword; import in.koreatech.koin.domain.community.article.model.ArticleSearchKeywordIpMap; @@ -14,20 +30,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ZSetOperations.TypedTuple; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.Clock; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - @Slf4j @Service @RequiredArgsConstructor @@ -75,10 +77,11 @@ public void updateHotArticles() { @Transactional public void updateBusNoticeArticle() { - List
articles = articleRepository.findBusArticlesTop5OrderByCreatedAtDesc(); - LocalDate latestDate = articles.get(0).getCreatedAt().toLocalDate(); - List
latestArticles = articles.stream() - .filter(article -> article.getCreatedAt().toLocalDate().isEqual(latestDate)) + List articles = articleRepository.findBusArticlesTop5OrderByCreatedAtDesc( + PageRequest.of(0, 5)); + LocalDate latestDate = articles.get(0).createdAt().toLocalDate(); + List latestArticles = articles.stream() + .filter(article -> article.createdAt().toLocalDate().isEqual(latestDate)) .toList(); if (latestArticles.size() >= 2) { @@ -88,21 +91,23 @@ public void updateBusNoticeArticle() { int secondWeight = 0; // 제목(title)에 "사과"가 들어가면 후순위, "긴급"이 포함되면 우선순위 - if (first.getTitle().contains("사과")) + if (first.title().contains("사과")) firstWeight++; - if (first.getTitle().contains("긴급")) + if (first.title().contains("긴급")) firstWeight--; - if (second.getTitle().contains("사과")) + if (second.title().contains("사과")) secondWeight++; - if (second.getTitle().contains("긴급")) + if (second.title().contains("긴급")) secondWeight--; return Integer.compare(firstWeight, secondWeight); }) .toList(); } - busArticleRepository.save(BusNoticeArticle.from(latestArticles.get(0))); + + BusArticleProjection latestArticle = latestArticles.get(0); + busArticleRepository.save(BusNoticeArticle.of(latestArticle.id(), latestArticle.title())); } @Transactional @@ -130,9 +135,10 @@ private void syncAllIpSearchCounts() { String ipAddress = ipKey.replace(IP_SEARCH_COUNT_PREFIX, ""); for (Map.Entry entry : keywordSearchCounts.entrySet()) { - String searchedKeyword = (String) entry.getKey(); + String searchedKeyword = (String)entry.getKey(); int searchCount = Integer.parseInt(entry.getValue().toString()); - if (searchCount <= 0) continue; + if (searchCount <= 0) + continue; articleSearchKeywordRepository.findByKeyword(searchedKeyword).ifPresent(keywordEntity -> { ipMapRepository.findByArticleSearchKeywordAndIpAddress(keywordEntity, ipAddress)