Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 방 검색 기능 구현 #121

Merged
merged 8 commits into from
Nov 20, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.moabam.api.domain.room.Routine;
import com.moabam.api.domain.room.repository.CertificationsSearchRepository;
import com.moabam.api.domain.room.repository.ParticipantSearchRepository;
import com.moabam.api.domain.room.repository.RoomRepository;
import com.moabam.api.domain.room.repository.RoomSearchRepository;
import com.moabam.api.domain.room.repository.RoutineSearchRepository;
import com.moabam.api.dto.room.CertificationImageResponse;
Expand All @@ -54,6 +55,7 @@ public class RoomSearchService {
private final ParticipantSearchRepository participantSearchRepository;
private final RoutineSearchRepository routineSearchRepository;
private final RoomSearchRepository roomSearchRepository;
private final RoomRepository roomRepository;
private final MemberService memberService;
private final RoomCertificationService roomCertificationService;
private final NotificationService notificationService;
Expand Down Expand Up @@ -116,7 +118,38 @@ public RoomsHistoryResponse getJoinHistory(Long memberId) {
public SearchAllRoomsResponse searchAllRooms(@Nullable RoomType roomType, @Nullable Long roomId) {
List<SearchAllRoomResponse> searchAllRoomResponses = new ArrayList<>();
List<Room> rooms = new ArrayList<>(roomSearchRepository.findAllWithNoOffset(roomType, roomId));
boolean hasNext = isHasNext(searchAllRoomResponses, rooms);

return RoomMapper.toSearchAllRoomsResponse(hasNext, searchAllRoomResponses);
}

public SearchAllRoomsResponse search(String keyword, @Nullable RoomType roomType, @Nullable Long roomId) {
List<SearchAllRoomResponse> searchAllRoomResponses = new ArrayList<>();
List<Room> rooms = new ArrayList<>();

if (roomId == null && roomType == null) {
rooms = new ArrayList<>(roomRepository.searchByKeyword(keyword));
}

if (roomId == null && roomType != null) {
rooms = new ArrayList<>(roomRepository.searchByKeywordAndRoomType(keyword, roomType.name()));
}

if (roomId != null && roomType == null) {
rooms = new ArrayList<>(roomRepository.searchByKeywordAndRoomId(keyword, roomId));
}

if (roomId != null && roomType != null) {
rooms = new ArrayList<>(
roomRepository.searchByKeywordAndRoomIdAndRoomType(keyword, roomType.name(), roomId));
}

boolean hasNext = isHasNext(searchAllRoomResponses, rooms);

return RoomMapper.toSearchAllRoomsResponse(hasNext, searchAllRoomResponses);
}

private boolean isHasNext(List<SearchAllRoomResponse> searchAllRoomResponses, List<Room> rooms) {
boolean hasNext = false;

if (rooms.size() > ROOM_FIXED_SEARCH_SIZE) {
Expand All @@ -138,8 +171,7 @@ public SearchAllRoomsResponse searchAllRooms(@Nullable RoomType roomType, @Nulla
RoomMapper.toSearchAllRoomResponse(room, RoutineMapper.toRoutineResponses(filteredRoutines),
isPassword));
}

return RoomMapper.toSearchAllRoomsResponse(hasNext, searchAllRoomResponses);
return hasNext;
}

private List<RoutineResponse> getRoutineResponses(Long roomId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,46 @@
package com.moabam.api.domain.room.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.moabam.api.domain.room.Room;

public interface RoomRepository extends JpaRepository<Room, Long> {

@Query(value = "select distinct rm.* from room rm left join routine rt on rm.id = rt.room_id "
+ "where rm.title like %:keyword% "
+ "or rm.manager_nickname like %:keyword% "
+ "or rt.content like %:keyword% "
+ "order by rm.id desc limit 11", nativeQuery = true)
List<Room> searchByKeyword(@Param(value = "keyword") String keyword);

@Query(value = "select distinct rm.* from room rm left join routine rt on rm.id = rt.room_id "
+ "where (rm.title like %:keyword% "
+ "or rm.manager_nickname like %:keyword% "
+ "or rt.content like %:keyword%) "
+ "and rm.room_type = :roomType "
+ "order by rm.id desc limit 11", nativeQuery = true)
List<Room> searchByKeywordAndRoomType(@Param(value = "keyword") String keyword,
@Param(value = "roomType") String roomType);

@Query(value = "select distinct rm.* from room rm left join routine rt on rm.id = rt.room_id "
+ "where (rm.title like %:keyword% "
+ "or rm.manager_nickname like %:keyword% "
+ "or rt.content like %:keyword%) "
+ "and rm.id < :roomId "
+ "order by rm.id desc limit 11", nativeQuery = true)
List<Room> searchByKeywordAndRoomId(@Param(value = "keyword") String keyword, @Param(value = "roomId") Long roomId);

@Query(value = "select distinct rm.* from room rm left join routine rt on rm.id = rt.room_id "
+ "where rm.title like %:keyword% "
+ "or rm.manager_nickname like %:keyword% "
+ "or rt.content like %:keyword% "
+ "and rm.room_type = :roomType "
+ "and rm.id < :roomId "
+ "order by rm.id desc limit 11", nativeQuery = true)
List<Room> searchByKeywordAndRoomIdAndRoomType(@Param(value = "keyword") String keyword,
@Param(value = "roomType") String roomType, @Param(value = "roomId") Long roomId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복된 쿼리 값들 default 메서드로 하셔도 되는거 아닌가요?

}
9 changes: 9 additions & 0 deletions src/main/java/com/moabam/api/presentation/RoomController.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,13 @@ public SearchAllRoomsResponse searchAllRooms(@RequestParam(value = "type", requi

return roomSearchService.searchAllRooms(roomType, roomId);
}

@GetMapping("/search")
@ResponseStatus(HttpStatus.OK)
public SearchAllRoomsResponse search(@RequestParam(value = "keyword") String keyword,
@RequestParam(value = "type", required = false) RoomType roomType,
@RequestParam(value = "roomId", required = false) Long roomId) {

return roomSearchService.search(keyword, roomType, roomId);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.moabam.api.application.room;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.anyList;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.spy;
import static org.mockito.BDDMockito.when;

import java.time.LocalDate;
import java.time.LocalDateTime;
Expand All @@ -21,6 +24,7 @@
import com.moabam.api.domain.room.Routine;
import com.moabam.api.domain.room.repository.CertificationsSearchRepository;
import com.moabam.api.domain.room.repository.ParticipantSearchRepository;
import com.moabam.api.domain.room.repository.RoomRepository;
import com.moabam.api.domain.room.repository.RoomSearchRepository;
import com.moabam.api.domain.room.repository.RoutineSearchRepository;
import com.moabam.api.dto.room.MyRoomsResponse;
Expand Down Expand Up @@ -52,6 +56,9 @@ class RoomSearchServiceTest {
@Mock
private RoomCertificationService certificationService;

@Mock
private RoomRepository roomRepository;

@DisplayName("유저가 참여중인 방 목록 조회 성공")
@Test
void get_my_rooms_success() {
Expand Down Expand Up @@ -304,4 +311,101 @@ void search_last_page_all_morning_night_rooms_success() {
assertThat(searchAllRoomsResponse.rooms().get(0).id()).isEqualTo(11L);
assertThat(searchAllRoomsResponse.rooms().get(3).id()).isEqualTo(14L);
}

@DisplayName("전체 방 제목, 방장 이름, 루틴 내용으로 검색 성공 - 최초 조회")
@Test
void search_room_by_title_manager_nickname_routine_success() {
// given
Room room1 = spy(RoomFixture.room("아침 - 첫 번째 방", RoomType.MORNING, 10, "1234"));
Room room2 = spy(RoomFixture.room("아침 - 두 번째 방", RoomType.MORNING, 9));
Room room3 = spy(RoomFixture.room("밤 - 세 번째 방", RoomType.NIGHT, 22));
Room room4 = spy(RoomFixture.room("아침 - 네 번째 방", RoomType.MORNING, 7));
Room room5 = spy(RoomFixture.room("밤 - 다섯 번째 방", RoomType.NIGHT, 23, "5869"));
Room room6 = spy(RoomFixture.room("아침 - 여섯 번째 방", RoomType.MORNING, 8));
Room room7 = spy(RoomFixture.room("밤 - 일곱 번째 방", RoomType.NIGHT, 20));
Room room8 = spy(RoomFixture.room("밤 - 여덟 번째 방", RoomType.NIGHT, 1, "5236"));
Room room9 = spy(RoomFixture.room("아침 - 아홉 번째 방", RoomType.MORNING, 4));
Room room10 = spy(RoomFixture.room("밤 - 열 번째 방", RoomType.NIGHT, 1, "97979"));
Room room11 = spy(RoomFixture.room("밤 - 열하나 번째 방", RoomType.NIGHT, 22));
Room room12 = spy(RoomFixture.room("아침 - 열둘 번째 방", RoomType.MORNING, 10));
Room room13 = spy(RoomFixture.room("밤 - 열셋 번째 방", RoomType.NIGHT, 2));
Room room14 = spy(RoomFixture.room("밤 - 열넷 번째 방", RoomType.NIGHT, 21));

given(room4.getId()).willReturn(4L);
given(room5.getId()).willReturn(5L);
given(room6.getId()).willReturn(6L);
given(room7.getId()).willReturn(7L);
given(room8.getId()).willReturn(8L);
given(room9.getId()).willReturn(9L);
given(room10.getId()).willReturn(10L);
given(room11.getId()).willReturn(11L);
given(room12.getId()).willReturn(12L);
given(room13.getId()).willReturn(13L);
given(room14.getId()).willReturn(14L);

List<Room> rooms = List.of(room4, room5, room6, room7, room8, room9, room10, room11, room12, room13, room14);

Routine routine9 = spy(RoomFixture.routine(room5, "방5의 루틴1"));
Routine routine10 = spy(RoomFixture.routine(room5, "방5의 루틴2"));

Routine routine11 = spy(RoomFixture.routine(room6, "방6의 루틴1"));
Routine routine12 = spy(RoomFixture.routine(room6, "방6의 루틴2"));

Routine routine13 = spy(RoomFixture.routine(room7, "방7의 루틴1"));
Routine routine14 = spy(RoomFixture.routine(room7, "방7의 루틴2"));

Routine routine15 = spy(RoomFixture.routine(room8, "방8의 루틴1"));
Routine routine16 = spy(RoomFixture.routine(room8, "방8의 루틴2"));

Routine routine17 = spy(RoomFixture.routine(room9, "방9의 루틴1"));
Routine routine18 = spy(RoomFixture.routine(room9, "방9의 루틴2"));

Routine routine19 = spy(RoomFixture.routine(room10, "방10의 루틴1"));
Routine routine20 = spy(RoomFixture.routine(room10, "방10의 루틴2"));

Routine routine21 = spy(RoomFixture.routine(room11, "방11의 루틴1"));
Routine routine22 = spy(RoomFixture.routine(room11, "방11의 루틴2"));

Routine routine23 = spy(RoomFixture.routine(room12, "방12의 루틴1"));
Routine routine24 = spy(RoomFixture.routine(room12, "방12의 루틴2"));

Routine routine25 = spy(RoomFixture.routine(room13, "방13의 루틴1"));
Routine routine26 = spy(RoomFixture.routine(room13, "방13의 루틴2"));

Routine routine27 = spy(RoomFixture.routine(room14, "방14의 루틴1"));
Routine routine28 = spy(RoomFixture.routine(room14, "방14의 루틴2"));

given(routine9.getId()).willReturn(9L);
given(routine10.getId()).willReturn(10L);
given(routine11.getId()).willReturn(11L);
given(routine12.getId()).willReturn(12L);
given(routine13.getId()).willReturn(13L);
given(routine14.getId()).willReturn(14L);
given(routine15.getId()).willReturn(15L);
given(routine16.getId()).willReturn(16L);
given(routine17.getId()).willReturn(17L);
given(routine18.getId()).willReturn(18L);
given(routine19.getId()).willReturn(19L);
given(routine20.getId()).willReturn(20L);
given(routine21.getId()).willReturn(21L);
given(routine22.getId()).willReturn(22L);
given(routine23.getId()).willReturn(23L);
given(routine24.getId()).willReturn(24L);
given(routine25.getId()).willReturn(25L);
given(routine26.getId()).willReturn(26L);

List<Routine> routines = List.of(routine9, routine10, routine11, routine12, routine13, routine14, routine15,
routine16, routine17, routine18, routine19, routine20, routine21, routine22, routine23, routine24,
routine25, routine26, routine27, routine28);

given(roomRepository.searchByKeyword("번째")).willReturn(rooms);
given(routineSearchRepository.findAllByRoomIds(anyList())).willReturn(routines);

// when
SearchAllRoomsResponse searchAllRoomsResponse = roomSearchService.search("번째", null, null);

// then
assertThat(searchAllRoomsResponse.hasNext()).isTrue();
assertThat(searchAllRoomsResponse.rooms()).hasSize(10);
}
}
Loading