Skip to content

Commit b180c94

Browse files
authored
fix: 키워드 페이징 조회를 단건 조회로 수정 (#2216)
* fix: 페이징 조회를 단일 조회로 수정 * chore: 코드 포멧팅 * fix: 미사용 리파지토리 메소드 삭제 * test: 테스트 코드 수정
1 parent 674e3a0 commit b180c94

3 files changed

Lines changed: 43 additions & 55 deletions

File tree

src/main/java/in/koreatech/koin/domain/community/keyword/repository/ArticleKeywordRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public interface ArticleKeywordRepository extends Repository<ArticleKeyword, Int
3030

3131
List<ArticleKeyword> findAll(Pageable pageable);
3232

33+
List<ArticleKeyword> findAll();
34+
3335
@Query("""
3436
SELECT new in.koreatech.koin.domain.community.article.dto.ArticleKeywordResult(k.id, k.keyword, COUNT(u))
3537
FROM ArticleKeywordUserMap u

src/main/java/in/koreatech/koin/domain/community/util/KeywordExtractor.java

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@
66
import java.util.Map;
77
import java.util.stream.Collectors;
88

9-
import org.springframework.data.domain.PageRequest;
10-
import org.springframework.data.domain.Pageable;
119
import org.springframework.stereotype.Service;
1210
import org.springframework.transaction.annotation.Transactional;
1311

12+
import in.koreatech.koin.common.event.ArticleKeywordEvent;
1413
import in.koreatech.koin.domain.community.article.model.Article;
1514
import in.koreatech.koin.domain.community.keyword.model.ArticleKeyword;
1615
import in.koreatech.koin.domain.community.keyword.model.ArticleKeywordUserMap;
17-
import in.koreatech.koin.common.event.ArticleKeywordEvent;
1816
import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordRepository;
1917
import in.koreatech.koin.domain.community.keyword.repository.ArticleKeywordUserMapRepository;
2018
import lombok.RequiredArgsConstructor;
@@ -24,56 +22,49 @@
2422
@Transactional(readOnly = true)
2523
public class KeywordExtractor {
2624

27-
private static final int KEYWORD_BATCH_SIZE = 100;
28-
2925
private final ArticleKeywordRepository articleKeywordRepository;
3026
private final ArticleKeywordUserMapRepository articleKeywordUserMapRepository;
3127

3228
public List<ArticleKeywordEvent> matchKeyword(List<Article> articles, Integer authorId) {
33-
Map<Integer, Map<Integer, String>> matchedKeywordByUserIdByArticleId = new LinkedHashMap<>();
34-
int offset = 0;
29+
List<ArticleKeyword> keywords = articleKeywordRepository.findAll();
3530

36-
while (true) {
37-
Pageable pageable = PageRequest.of(offset / KEYWORD_BATCH_SIZE, KEYWORD_BATCH_SIZE);
38-
List<ArticleKeyword> keywords = articleKeywordRepository.findAll(pageable);
31+
if (keywords.isEmpty()) {
32+
return List.of();
33+
}
3934

40-
if (keywords.isEmpty()) {
41-
break;
42-
}
43-
List<Integer> keywordIds = keywords.stream()
44-
.map(ArticleKeyword::getId)
45-
.toList();
46-
Map<Integer, List<ArticleKeywordUserMap>> userMapsByKeywordId = articleKeywordUserMapRepository
47-
.findAllByArticleKeywordIdIn(keywordIds)
48-
.stream()
49-
.filter(keywordUserMap -> !keywordUserMap.getIsDeleted())
50-
.collect(Collectors.groupingBy(
51-
keywordUserMap -> keywordUserMap.getArticleKeyword().getId(),
52-
LinkedHashMap::new,
53-
Collectors.toList()
54-
));
35+
List<Integer> keywordIds = keywords.stream()
36+
.map(ArticleKeyword::getId)
37+
.toList();
38+
Map<Integer, List<ArticleKeywordUserMap>> userMapsByKeywordId = articleKeywordUserMapRepository
39+
.findAllByArticleKeywordIdIn(keywordIds)
40+
.stream()
41+
.filter(keywordUserMap -> !keywordUserMap.getIsDeleted())
42+
.collect(Collectors.groupingBy(
43+
keywordUserMap -> keywordUserMap.getArticleKeyword().getId(),
44+
LinkedHashMap::new,
45+
Collectors.toList()
46+
));
5547

56-
for (Article article : articles) {
57-
String title = article.getTitle();
58-
for (ArticleKeyword keyword : keywords) {
59-
if (!title.contains(keyword.getKeyword())) {
60-
continue;
61-
}
62-
Map<Integer, String> matchedKeywordByUserId = matchedKeywordByUserIdByArticleId
63-
.computeIfAbsent(article.getId(), ignored -> new LinkedHashMap<>());
48+
Map<Integer, Map<Integer, String>> matchedKeywordByUserIdByArticleId = new LinkedHashMap<>();
49+
for (Article article : articles) {
50+
String title = article.getTitle();
51+
for (ArticleKeyword keyword : keywords) {
52+
if (!title.contains(keyword.getKeyword())) {
53+
continue;
54+
}
55+
Map<Integer, String> matchedKeywordByUserId = matchedKeywordByUserIdByArticleId
56+
.computeIfAbsent(article.getId(), ignored -> new LinkedHashMap<>());
6457

65-
for (ArticleKeywordUserMap keywordUserMap :
66-
userMapsByKeywordId.getOrDefault(keyword.getId(), List.of())) {
67-
Integer userId = keywordUserMap.getUser().getId();
68-
matchedKeywordByUserId.merge(
69-
userId,
70-
keyword.getKeyword(),
71-
this::pickHigherPriorityKeyword
72-
);
73-
}
58+
for (ArticleKeywordUserMap keywordUserMap :
59+
userMapsByKeywordId.getOrDefault(keyword.getId(), List.of())) {
60+
Integer userId = keywordUserMap.getUser().getId();
61+
matchedKeywordByUserId.merge(
62+
userId,
63+
keyword.getKeyword(),
64+
this::pickHigherPriorityKeyword
65+
);
7466
}
7567
}
76-
offset += KEYWORD_BATCH_SIZE;
7768
}
7869

7970
List<ArticleKeywordEvent> keywordEvents = new ArrayList<>();

src/test/java/in/koreatech/koin/unit/domain/community/util/KeywordExtractorTest.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import org.mockito.InjectMocks;
1616
import org.mockito.Mock;
1717
import org.mockito.junit.jupiter.MockitoExtension;
18-
import org.springframework.data.domain.Pageable;
1918
import org.springframework.test.util.ReflectionTestUtils;
2019

2120
import in.koreatech.koin.common.event.ArticleKeywordEvent;
@@ -51,9 +50,8 @@ void matchKeyword_withMultipleMatchedKeywordsInSingleArticle_createsSingleEvent(
5150
ArticleKeyword keywordA = createKeyword(1, "근로", subscriber);
5251
ArticleKeyword keywordB = createKeyword(2, "근로장학", subscriber);
5352

54-
when(articleKeywordRepository.findAll(any(Pageable.class)))
55-
.thenReturn(List.of(keywordA, keywordB))
56-
.thenReturn(List.of());
53+
when(articleKeywordRepository.findAll())
54+
.thenReturn(List.of(keywordA, keywordB));
5755
when(articleKeywordUserMapRepository.findAllByArticleKeywordIdIn(any()))
5856
.thenReturn(List.of(
5957
keywordA.getArticleKeywordUserMaps().get(0),
@@ -79,9 +77,8 @@ void matchKeyword_whenNoKeywordsMatch_returnsEmptyResult() {
7977
User subscriber = UserFixture.id_설정_코인_유저(1);
8078
ArticleKeyword keyword = createKeyword(1, "장학금", subscriber);
8179

82-
when(articleKeywordRepository.findAll(any(Pageable.class)))
83-
.thenReturn(List.of(keyword))
84-
.thenReturn(List.of());
80+
when(articleKeywordRepository.findAll())
81+
.thenReturn(List.of(keyword));
8582
when(articleKeywordUserMapRepository.findAllByArticleKeywordIdIn(any()))
8683
.thenReturn(List.of(keyword.getArticleKeywordUserMaps().get(0)));
8784

@@ -106,9 +103,8 @@ void matchKeyword_withMultipleArticles_createsEventPerArticle() {
106103
ArticleKeyword firstKeyword = createKeyword(1, "근로", firstSubscriber);
107104
ArticleKeyword secondKeyword = createKeyword(2, "장학금", secondSubscriber);
108105

109-
when(articleKeywordRepository.findAll(any(Pageable.class)))
110-
.thenReturn(List.of(firstKeyword, secondKeyword))
111-
.thenReturn(List.of());
106+
when(articleKeywordRepository.findAll())
107+
.thenReturn(List.of(firstKeyword, secondKeyword));
112108
when(articleKeywordUserMapRepository.findAllByArticleKeywordIdIn(any()))
113109
.thenReturn(List.of(
114110
firstKeyword.getArticleKeywordUserMaps().get(0),
@@ -128,8 +124,7 @@ void matchKeyword_withMultipleArticles_createsEventPerArticle() {
128124
@DisplayName("등록된 키워드가 없으면 빈 결과를 반환한다.")
129125
void matchKeyword_whenNoKeywordsExist_returnsEmptyResult() {
130126
Article article = mock(Article.class);
131-
when(article.getId()).thenReturn(1);
132-
when(articleKeywordRepository.findAll(any(Pageable.class))).thenReturn(List.of());
127+
when(articleKeywordRepository.findAll()).thenReturn(List.of());
133128

134129
List<ArticleKeywordEvent> result = keywordExtractor.matchKeyword(List.of(article), null);
135130

0 commit comments

Comments
 (0)