Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.truve.platform.musical.show.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.truve.platform.common.response.ApiResult;
import com.truve.platform.musical.show.dto.SearchResponse;
import com.truve.platform.musical.show.service.SearchService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/musical")
public class SearchController {

private final SearchService searchService;

@Operation(
summary = "통합 검색",
description = "공연명/배우명으로 통합 검색 결과를 조회합니다."
)
@GetMapping("/search")
public ApiResult<SearchResponse.SearchResult> search(
@Parameter(description = "검색어(공백 입력 시 빈 결과 반환)")
@RequestParam(name = "keyword", required = false) String keyword,
@Parameter(description = "아티스트 검색 시작 위치")
@RequestParam(name = "artistOffset", defaultValue = "0") int artistOffset,
@Parameter(description = "아티스트 한 페이지 개수")
@RequestParam(name = "artistLimit", defaultValue = "20") int artistLimit,
@Parameter(description = "공연 검색 시작 위치")
@RequestParam(name = "showOffset", defaultValue = "0") int showOffset,
@Parameter(description = "공연 한 페이지 개수")
@RequestParam(name = "showLimit", defaultValue = "20") int showLimit
) {
return ApiResult.ok(searchService.search(keyword, artistOffset, artistLimit, showOffset, showLimit));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.truve.platform.musical.show.dto;

import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

public class SearchResponse {

@Getter
@AllArgsConstructor
@Builder
public static class SearchResult {
private String keyword;
private int artistCount;
private int showCount;
private boolean hasMoreArtists;
private boolean hasMoreShows;
private List<ArtistSummary> artists;
private List<ShowSummary> shows;

public static SearchResult of(
String keyword,
List<ArtistSummary> artists,
List<ShowSummary> shows,
int totalArtistCount,
int totalShowCount,
boolean hasMoreArtists,
boolean hasMoreShows
) {
return SearchResult.builder()
.keyword(keyword)
.artistCount(totalArtistCount)
.showCount(totalShowCount)
.hasMoreArtists(hasMoreArtists)
.hasMoreShows(hasMoreShows)
.artists(artists)
.shows(shows)
.build();
}

public static SearchResult empty(String keyword) {
return SearchResult.builder()
.keyword(keyword)
.artistCount(0)
.showCount(0)
.hasMoreArtists(false)
.hasMoreShows(false)
.artists(List.of())
.shows(List.of())
.build();
}
}

@Getter
@AllArgsConstructor
@Builder
public static class ArtistSummary {
private Long artistId;
private String artistName;
private String profileImageUrl;
private String appearanceInfo;

public static ArtistSummary of(
Long artistId,
String artistName,
String profileImageUrl,
String appearanceInfo
) {
return ArtistSummary.builder()
.artistId(artistId)
.artistName(artistName)
.profileImageUrl(profileImageUrl)
.appearanceInfo(appearanceInfo)
.build();
}
}

@Getter
@AllArgsConstructor
@Builder
public static class ShowSummary {
private Long showId;
private String posterUrl;
private String title;
private String venueName;
private String date;

public static ShowSummary of(
Long showId,
String posterUrl,
String title,
String venueName,
String date
) {
return ShowSummary.builder()
.showId(showId)
.posterUrl(posterUrl)
.title(title)
.venueName(venueName)
.date(date)
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
package com.truve.platform.musical.show.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.truve.platform.musical.show.domain.entity.Artist;

public interface ArtistRepository extends JpaRepository<Artist, Long> {
}
interface ArtistSearchProjection {
Long getArtistId();

String getArtistName();

String getProfileImg();
}

@Query("""
select
a.id as artistId,
a.name as artistName,
a.profileImg as profileImg
from Artist a
where a.name like concat('%', :keyword, '%')
order by
case
when lower(a.name) = lower(:keyword) then 0
else 1
end asc,
a.name asc,
a.id asc
""")
List<ArtistSearchProjection> searchArtists(@Param("keyword") String keyword);

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.truve.platform.musical.show.repository;

import java.time.LocalDateTime;
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -9,6 +10,21 @@
import com.truve.platform.musical.show.domain.entity.ShowCasting;

public interface ShowCastingRepository extends JpaRepository<ShowCasting, Long> {
interface ArtistAppearanceProjection {
Long getArtistId();

Long getShowId();

String getShowTitle();

String getPosterImg();

String getVenueName();

LocalDateTime getStartTime();

LocalDateTime getEndTime();
}

@Query("""
select c
Expand All @@ -21,4 +37,27 @@ public interface ShowCastingRepository extends JpaRepository<ShowCasting, Long>
c.id asc
""")
List<ShowCasting> findAllByShowId(@Param("showId") Long showId);
}

@Query("""
select distinct
sc.artist.id as artistId,
sc.show.id as showId,
sc.show.title as showTitle,
sc.show.posterImg as posterImg,
v.name as venueName,
sc.show.startTime as startTime,
sc.show.endTime as endTime
from ShowCasting sc
left join Venue v on v.id = sc.show.venueId
where sc.artist.id in :artistIds
order by
sc.artist.id asc,
case
when sc.show.startTime is null then 1
else 0
end asc,
sc.show.startTime desc,
sc.show.id desc
""")
List<ArtistAppearanceProjection> findAppearanceInfoByArtistIds(@Param("artistIds") List<Long> artistIds);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.truve.platform.musical.show.repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -13,6 +15,19 @@
import com.truve.platform.musical.show.domain.entity.Show;

public interface ShowRepository extends JpaRepository<Show, Long> {
interface ShowSearchProjection {
Long getShowId();

String getPosterImg();

String getTitle();

String getVenueName();

LocalDateTime getStartTime();

LocalDateTime getEndTime();
}

@Query("""
select s
Expand Down Expand Up @@ -126,11 +141,41 @@ Page<Show> findHomeShowsOrderByReviewCount(
from Show p
where p.id = :showId
""")
java.util.Optional<Show> findDetailById(@Param("showId") Long showId);
Optional<Show> findDetailById(@Param("showId") Long showId);

default Show findByIdOrThrow(Long showId) {
return findDetailById(showId).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_SHOW)
);
}
}

@Query("""
select
s.id as showId,
s.posterImg as posterImg,
s.title as title,
v.name as venueName,
s.startTime as startTime,
s.endTime as endTime
from Show s
left join Venue v on v.id = s.venueId
where s.title like concat('%', :keyword, '%')
and (s.endTime is null or s.endTime >= :now)
order by
case
when lower(s.title) = lower(:keyword) then 0
else 1
end asc,
case
when s.startTime is null then 1
else 0
end asc,
s.startTime desc,
s.id desc
""")
List<ShowSearchProjection> searchShows(
@Param("keyword") String keyword,
@Param("now") LocalDateTime now
);

}
Loading