Skip to content

Commit

Permalink
[BE] feat: 축제 대학교 검색 기능 보완 및 정렬(#926) (#927)
Browse files Browse the repository at this point in the history
* feat: 축제 검색 시 ~대 ~대학교를 붙히지 않더라도 검색 가능 및 진행, 예정, 종료 순 정렬 적용

* refactor: 아티스트 축제 조회 로직 리팩토링

* refactor: 축제 정렬 리팩토링

* refactor: 개행 및 EmptyList 반환
  • Loading branch information
BGuga authored May 15, 2024
1 parent 30fc51e commit a5bf7c3
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package com.festago.festival.application;

import static com.festago.festival.repository.FestivalFilter.END;
import static com.festago.festival.repository.FestivalFilter.PLANNED;
import static com.festago.festival.repository.FestivalFilter.PROGRESS;

import com.festago.festival.dto.FestivalSearchV1Response;
import com.festago.festival.repository.ArtistFestivalSearchV1QueryDslRepository;
import com.festago.festival.repository.FestivalFilter;
import com.festago.festival.repository.SchoolFestivalSearchV1QueryDslRepository;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -15,16 +25,65 @@
@RequiredArgsConstructor
public class FestivalSearchV1QueryService {

private static final Pattern SCHOOL_PATTERN = Pattern.compile(".*대(학교)?$");

private final ArtistFestivalSearchV1QueryDslRepository artistFestivalSearchV1QueryDslRepository;
private final SchoolFestivalSearchV1QueryDslRepository schoolFestivalSearchV1QueryDslRepository;

public List<FestivalSearchV1Response> search(String keyword) {
Matcher schoolMatcher = SCHOOL_PATTERN.matcher(keyword);
if (schoolMatcher.matches()) {
return schoolFestivalSearchV1QueryDslRepository.executeSearch(keyword);
return sortFestival(findFestivals(keyword));
}

private List<FestivalSearchV1Response> findFestivals(String keyword) {
if (artistFestivalSearchV1QueryDslRepository.existsByName(keyword)) {
return artistFestivalSearchV1QueryDslRepository.executeSearch(keyword);
}
return schoolFestivalSearchV1QueryDslRepository.executeSearch(keyword);
}

private List<FestivalSearchV1Response> sortFestival(List<FestivalSearchV1Response> festivals) {
Map<FestivalFilter, List<FestivalSearchV1Response>> festivalByStatus = divideByStatus(festivals);
List<FestivalSearchV1Response> result = new ArrayList<>();
for (FestivalFilter festivalFilter : determineFestivalOrder()) {
List<FestivalSearchV1Response> festivalsByFilter = festivalByStatus.getOrDefault(festivalFilter,
Collections.emptyList());
sortByStatus(festivalFilter, festivalsByFilter);
result.addAll(festivalsByFilter);
}
return result;
}

private Map<FestivalFilter, List<FestivalSearchV1Response>> divideByStatus(
List<FestivalSearchV1Response> festivals
) {
return festivals.stream()
.collect(Collectors.groupingBy(
this::determineStatus,
() -> new EnumMap<>(FestivalFilter.class),
Collectors.toList()
));
}

private FestivalFilter determineStatus(FestivalSearchV1Response festival) {
LocalDate now = LocalDate.now();
if (now.isAfter(festival.endDate())) {
return END;
}
if (now.isBefore(festival.startDate())) {
return PLANNED;
}
return PROGRESS;
}

private List<FestivalFilter> determineFestivalOrder() {
return List.of(PROGRESS, PLANNED, END);
}

private void sortByStatus(
FestivalFilter status,
List<FestivalSearchV1Response> festivals) {

switch (status) {
case END -> festivals.sort(Comparator.comparing(FestivalSearchV1Response::endDate).reversed());
case PROGRESS, PLANNED -> festivals.sort(Comparator.comparing(FestivalSearchV1Response::startDate));
}
return artistFestivalSearchV1QueryDslRepository.executeSearch(keyword);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,38 @@ public ArtistFestivalSearchV1QueryDslRepository() {
}

public List<FestivalSearchV1Response> executeSearch(String keyword) {
return select(new QFestivalSearchV1Response(
festival.id,
festival.name,
festival.festivalDuration.startDate,
festival.festivalDuration.endDate,
festival.posterImageUrl,
festivalQueryInfo.artistInfo)
)
.from(artist)
.innerJoin(stageArtist).on(stageArtist.artistId.eq(artist.id))
.innerJoin(stage).on(stage.id.eq(stageArtist.stageId))
.innerJoin(festival).on(festival.id.eq(stage.festival.id))
.innerJoin(festivalQueryInfo).on(festival.id.eq(festivalQueryInfo.festivalId))
.where(getBooleanExpressionByKeyword(keyword))
.fetch();
}

private BooleanExpression getBooleanExpressionByKeyword(String keyword) {
int keywordLength = keyword.length();
if (keywordLength == 0) {
throw new BadRequestException(ErrorCode.INVALID_KEYWORD);
}
if (keywordLength == 1) {
return searchByEqual(keyword);
return artist.name.eq(keyword);
}
return searchByLike(keyword);
}

private List<FestivalSearchV1Response> searchByEqual(String keyword) {
return searchByExpression(artist.name.eq(keyword));
}

private List<FestivalSearchV1Response> searchByExpression(BooleanExpression expression) {
return select(
new QFestivalSearchV1Response(
festival.id,
festival.name,
festival.festivalDuration.startDate,
festival.festivalDuration.endDate,
festival.posterImageUrl,
festivalQueryInfo.artistInfo))
.from(artist)
.innerJoin(stageArtist).on(expression.and(stageArtist.artistId.eq(artist.id)))
.innerJoin(stage).on(stage.id.eq(stageArtist.stageId))
.innerJoin(festival).on(festival.id.eq(stage.festival.id))
.innerJoin(festivalQueryInfo).on(festival.id.eq(festivalQueryInfo.festivalId))
.where(expression)
.fetch();
return artist.name.contains(keyword);
}

private List<FestivalSearchV1Response> searchByLike(String keyword) {
return searchByExpression(artist.name.contains(keyword));
public boolean existsByName(String keyword) {
return !selectFrom(artist)
.where(getBooleanExpressionByKeyword(keyword))
.fetch()
.isEmpty();
}
}
Loading

0 comments on commit a5bf7c3

Please sign in to comment.