Skip to content

Commit 8c12237

Browse files
authored
Merge pull request #321 from prgrms-web-devcourse-final-project/feat/#320
[Community] 검색 기능 추가
2 parents 35df8a6 + 7bef944 commit 8c12237

8 files changed

Lines changed: 134 additions & 1 deletion

File tree

src/main/java/com/back/web7_9_codecrete_be/domain/community/comment/service/CommentService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public CommentPageResponse<CommentResponse> getComments(Long postId, int page) {
4747

4848
Pageable pageable = PageRequest.of(
4949
page - 1,
50-
20,
50+
10,
5151
Sort.by(Sort.Direction.ASC, "createdDate")
5252
);
5353

src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/JoinPostController.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
import com.back.web7_9_codecrete_be.global.rq.Rq;
99
import com.back.web7_9_codecrete_be.global.rsData.RsData;
1010
import io.swagger.v3.oas.annotations.Operation;
11+
import io.swagger.v3.oas.annotations.Parameter;
12+
import io.swagger.v3.oas.annotations.media.Schema;
1113
import io.swagger.v3.oas.annotations.tags.Tag;
1214
import jakarta.validation.Valid;
1315
import lombok.RequiredArgsConstructor;
16+
import org.springframework.data.domain.Pageable;
1417
import org.springframework.web.bind.annotation.*;
1518

19+
import java.util.List;
20+
1621
@RestController
1722
@RequestMapping("/api/v1/join")
1823
@RequiredArgsConstructor
@@ -73,4 +78,23 @@ public RsData<?> close(
7378
joinPostService.close(postId, user.getId());
7479
return RsData.success("구인글이 마감되었습니다.");
7580
}
81+
82+
@Operation(summary = "구인글 검색", description = "제목 또는 내용에 키워드를 포함하고 있는 구인글을 검색합니다.")
83+
@GetMapping("/search")
84+
public RsData<List<JoinPostResponse>> search(
85+
@Schema(description = """
86+
<h3>검색어가 되는 Keyword입니다.</h3>
87+
<hr/>
88+
<b>?keyword={keyword}</b> 로 값을 넘기시면 됩니다.<br/>
89+
제목 또는 내용에 해당 문자열을 포함하는 구인글을
90+
페이징된 만큼 반환합니다.
91+
""")
92+
@RequestParam String keyword,
93+
@Schema(description = "페이징 처리 또는 무한 스크롤 구현에 사용하는 Pageable 객체입니다.")
94+
@Parameter(hidden = true) Pageable pageable
95+
) {
96+
return RsData.success(
97+
joinPostService.searchByKeyword(keyword, pageable)
98+
);
99+
}
76100
}

src/main/java/com/back/web7_9_codecrete_be/domain/community/post/controller/ReviewPostController.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99
import com.back.web7_9_codecrete_be.global.rq.Rq;
1010
import com.back.web7_9_codecrete_be.global.rsData.RsData;
1111
import io.swagger.v3.oas.annotations.Operation;
12+
import io.swagger.v3.oas.annotations.Parameter;
13+
import io.swagger.v3.oas.annotations.media.Schema;
1214
import io.swagger.v3.oas.annotations.tags.Tag;
1315
import jakarta.validation.Valid;
1416
import lombok.RequiredArgsConstructor;
17+
import org.springframework.data.domain.Pageable;
1518
import org.springframework.http.MediaType;
1619
import org.springframework.web.bind.annotation.*;
1720

21+
import java.util.List;
22+
1823
@RestController
1924
@RequestMapping("/api/v1/reviews")
2025
@RequiredArgsConstructor
@@ -86,4 +91,24 @@ public RsData<?> getReviewsByConcert(
8691
reviewPostService.getReviewsByConcert(concertId)
8792
);
8893
}
94+
95+
@Operation(summary = "후기 게시글 검색", description = "제목 또는 내용에 키워드를 포함하고 있는 후기 게시글을 검색합니다.")
96+
@GetMapping("/search")
97+
public RsData<List<ReviewPostResponse>> search(
98+
@Schema(description = """
99+
<h3>검색어가 되는 Keyword입니다.</h3>
100+
<hr/>
101+
<b>?keyword={keyword}</b> 로 값을 넘기시면 됩니다.<br/>
102+
제목 또는 내용에 해당 문자열을 포함하는
103+
후기 게시글을 페이징된 만큼 반환합니다.
104+
""")
105+
@RequestParam String keyword,
106+
107+
@Schema(description = "페이징 처리 또는 무한 스크롤 구현에 사용하는 Pageable 객체입니다.")
108+
@Parameter(hidden = true) Pageable pageable
109+
) {
110+
return RsData.success(
111+
reviewPostService.searchByKeyword(keyword, pageable)
112+
);
113+
}
89114
}

src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/JoinPostRepository.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,29 @@
44
import org.springframework.data.domain.Page;
55
import org.springframework.data.domain.Pageable;
66
import org.springframework.data.jpa.repository.JpaRepository;
7+
import org.springframework.data.jpa.repository.Query;
8+
import org.springframework.data.repository.query.Param;
9+
10+
import java.util.List;
711

812
public interface JoinPostRepository extends JpaRepository<JoinPost, Long> {
913
Page<JoinPost> findByPost_UserId(Long userId, Pageable pageable);
14+
15+
@Query("""
16+
SELECT
17+
jp
18+
FROM
19+
JoinPost jp
20+
JOIN FETCH
21+
jp.post p
22+
WHERE
23+
p.title LIKE %:keyword%
24+
OR p.content LIKE %:keyword%
25+
ORDER BY
26+
p.createdDate DESC
27+
""")
28+
List<JoinPost> searchByKeyword(
29+
@Param("keyword") String keyword,
30+
Pageable pageable
31+
);
1032
}

src/main/java/com/back/web7_9_codecrete_be/domain/community/post/repository/ReviewPostRepository.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,29 @@
44
import org.springframework.data.domain.Page;
55
import org.springframework.data.domain.Pageable;
66
import org.springframework.data.jpa.repository.JpaRepository;
7+
import org.springframework.data.jpa.repository.Query;
8+
import org.springframework.data.repository.query.Param;
9+
10+
import java.util.List;
711

812
public interface ReviewPostRepository extends JpaRepository<ReviewPost, Long> {
913
Page<ReviewPost> findByPost_UserId(Long userId, Pageable pageable);
14+
15+
@Query("""
16+
SELECT
17+
rp
18+
FROM
19+
ReviewPost rp
20+
JOIN FETCH
21+
rp.post p
22+
WHERE
23+
p.title LIKE %:keyword%
24+
OR p.content LIKE %:keyword%
25+
ORDER BY
26+
p.createdDate DESC
27+
""")
28+
List<ReviewPost> searchByKeyword(
29+
@Param("keyword") String keyword,
30+
Pageable pageable
31+
);
1032
}

src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/JoinPostService.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414
import com.back.web7_9_codecrete_be.global.error.code.PostErrorCode;
1515
import com.back.web7_9_codecrete_be.global.error.exception.BusinessException;
1616
import lombok.RequiredArgsConstructor;
17+
import org.springframework.data.domain.Pageable;
1718
import org.springframework.stereotype.Service;
1819
import org.springframework.transaction.annotation.Transactional;
1920

21+
import java.util.List;
22+
2023
@Service
2124
@RequiredArgsConstructor
2225
public class JoinPostService {
@@ -117,4 +120,15 @@ public void close(Long postId, Long userId) {
117120

118121
joinPost.close(); // status = CLOSED
119122
}
123+
124+
public List<JoinPostResponse> searchByKeyword(String keyword, Pageable pageable) {
125+
if (keyword == null || keyword.isEmpty()) {
126+
throw new BusinessException(PostErrorCode.KEYWORD_IS_NULL);
127+
}
128+
129+
return joinPostRepository.searchByKeyword(keyword, pageable)
130+
.stream()
131+
.map(JoinPostResponse::from)
132+
.toList();
133+
}
120134
}

src/main/java/com/back/web7_9_codecrete_be/domain/community/post/service/ReviewPostService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.back.web7_9_codecrete_be.global.storage.ImageFileValidator;
2121
import lombok.RequiredArgsConstructor;
2222
import lombok.extern.slf4j.Slf4j;
23+
import org.springframework.data.domain.Pageable;
2324
import org.springframework.stereotype.Service;
2425
import org.springframework.transaction.annotation.Transactional;
2526
import org.springframework.web.multipart.MultipartFile;
@@ -268,5 +269,23 @@ private ReviewItemResponse toReviewItem(ReviewPost reviewPost) {
268269
.createdDate(reviewPost.getPost().getCreatedDate())
269270
.build();
270271
}
272+
273+
public List<ReviewPostResponse> searchByKeyword(String keyword, Pageable pageable) {
274+
if (keyword == null || keyword.isBlank()) {
275+
throw new BusinessException(PostErrorCode.KEYWORD_IS_NULL);
276+
}
277+
278+
return reviewPostRepository.searchByKeyword(keyword, pageable)
279+
.stream()
280+
.map(reviewPost -> {
281+
List<String> imageUrls = reviewPost.getImages()
282+
.stream()
283+
.map(ReviewImage::getImageUrl)
284+
.toList();
285+
286+
return ReviewPostResponse.from(reviewPost, imageUrls);
287+
})
288+
.toList();
289+
}
271290
}
272291

src/main/java/com/back/web7_9_codecrete_be/global/error/code/PostErrorCode.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ public enum PostErrorCode implements ErrorCode {
4040
HttpStatus.BAD_REQUEST,
4141
"P-130",
4242
"이미 삭제된 게시글입니다."
43+
),
44+
45+
// 검색 관련
46+
KEYWORD_IS_NULL(
47+
HttpStatus.BAD_REQUEST,
48+
"P-140",
49+
"검색어는 필수입니다."
4350
);
4451

4552
private final HttpStatus status;

0 commit comments

Comments
 (0)