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

이력서 조회순 정렬 기능 추가 #281

Merged
merged 5 commits into from
Feb 23, 2025
Merged
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
Expand Up @@ -118,7 +118,7 @@ public CommonResponse<List<PageableResumeResponse>> searchResumes(@RequestParam(
@RequestParam(name = "size") int size) {
//ResumeService를 통해 페이지네이션된 이력서 목록을 가져옵니다.
final Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Order.desc("createdAt")));
Page<Resume> resumes = resumeService.getResumePage(pageable);
Slice<Resume> resumes = resumeService.getResumePage(pageable);

List<PageableResumeResponse> resumeResponses = resumes.stream()
.map(ResumeConverter::toPageableResumeResponse)
Expand Down Expand Up @@ -151,4 +151,18 @@ public CommonResponse<?> deleteResume(@PathVariable("resume_id") Long resumeId)
resumeService.softDeleteResume(user, resumeId);
return CommonResponse.of(SuccessCode.RESUME_SOFT_DELETED, null);
}

@Operation(summary = "이력서 조회순으로 조회")
@GetMapping("/resumes/view")
public CommonResponse<List<PageableResumeResponse>> searchResumesByView(@RequestParam(name = "page") int page,
@RequestParam(name = "size") int size) {
final Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Order.desc("viewCount")));
Slice<Resume> resumeList = resumeService.getResumePage(pageable);

List<PageableResumeResponse> pageableResumeResponse = resumeList.stream()
.map(ResumeConverter::toPageableResumeResponse)
.collect(Collectors.toList());

return CommonResponse.of(SuccessCode.OK, pageableResumeResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public static PageableResumeResponse toPageableResumeResponse(Resume resume) {
.resumeId(resume.getId())
.resumeName(resume.getName())
.userName(resume.getUser().getUsername())
.viewCount(resume.getViewCount())
.resumeName(resume.getName())
Comment on lines +20 to 21
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate resumeName field.

The resumeName field is set twice in the builder. Remove the duplicate line to avoid confusion and potential issues.

Apply this diff to fix the duplication:

                .viewCount(resume.getViewCount())
-                .resumeName(resume.getName())
                .position(resume.getPosition().getValue())
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.viewCount(resume.getViewCount())
.resumeName(resume.getName())
.viewCount(resume.getViewCount())
.position(resume.getPosition().getValue())

.position(resume.getPosition().getValue())
.career(resume.getCareer())
Expand Down Expand Up @@ -54,6 +55,7 @@ public static ResumeDetailResponse toResumeDetailResponse(Resume resume, List<Fe
public static ResumeResponse toResumeResponse(Resume resume) {
return ResumeResponse.builder()
.resumeId(resume.getId())
.viewCount(resume.getViewCount())
.resumeName(resume.getName())
.userName(resume.getUser().getUsername())
.resumeName(resume.getName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Table;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -58,6 +59,10 @@ public class Resume extends BaseEntity {
// 이후 버전(더 최신 버전)
private Long laterResumeId;

// 조회수
@Column(name = "view_count")
private Long viewCount;

@Builder.Default
@OneToMany(mappedBy = "resume", cascade = CascadeType.ALL)
private List<ResumeTechStack> resumeTechStacks = new ArrayList<>();
Expand All @@ -77,6 +82,14 @@ public Resume(User user, String name, int career, Position position, ResumePdf r
this.career = career;
this.position = position;
this.resumePdf = resumePdf;
this.viewCount = 0L;
}

@PrePersist
public void prePersist() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Entity를 build할때 항상 viewCount는 0인데
왜 저장하기 전에 viewCount가 null인지 확인하는거야??

Copy link
Member Author

Choose a reason for hiding this comment

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

빌드할 때 0으로 설정하긴 했는데, 이후에 조회했을 때 DB 계속 0이 아니라 null로 저장이 되더라고 그래서 null값 허용 안하게 하려고 이렇게 했어

if (this.viewCount == null) {
this.viewCount = 0L;
}
}

public void addResumeTechStack(ResumeTechStack resumeTechStack) {
Expand All @@ -94,4 +107,8 @@ public void addResumePdf(ResumePdf resumePdf) {
public void updateLaterResumeId(Long id) {
this.laterResumeId = id;
}

public void increaseViewCount() {
this.viewCount++;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public class PageableResumeResponse {
private List<String> companyNames;
private int totalPage;
private int currentPage;
private Long viewCount;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ public class ResumeResponse {
private final String position;
private final List<String> techStackNames;
private List<String> companyNames;
private Long viewCount;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.techeer.backend.api.user.domain.User;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -24,4 +25,6 @@ public interface ResumeRepository extends JpaRepository<Resume, Long>, ResumeRep
Resume findFirstByUserOrderByCreatedAtDesc(User user);

Slice<Resume> findResumeByUser(User user);

Slice<Resume> findResumesByDeletedAtIsNull(Pageable pageable);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding view count sorting capability.

While the method correctly implements pagination for non-deleted resumes, it doesn't support the PR's objective of sorting resumes by view count. Consider adding a method that includes ordering by view count.

Here's a suggested implementation:

-    Slice<Resume> findResumesByDeletedAtIsNull(Pageable pageable);
+    Slice<Resume> findResumesByDeletedAtIsNullOrderByViewCountDesc(Pageable pageable);

Alternatively, you could use a custom query to have more control over the sorting:

+    @Query("SELECT r FROM Resume r WHERE r.deletedAt IS NULL ORDER BY r.viewCount DESC")
     Slice<Resume> findResumesByDeletedAtIsNull(Pageable pageable);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Slice<Resume> findResumesByDeletedAtIsNull(Pageable pageable);
Slice<Resume> findResumesByDeletedAtIsNullOrderByViewCountDesc(Pageable pageable);

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import com.techeer.backend.api.resume.exception.ResumeNotFoundException;
import com.techeer.backend.api.resume.repository.ResumeRepository;
import com.techeer.backend.api.user.domain.User;
import com.techeer.backend.global.error.ErrorCode;
import com.techeer.backend.global.error.exception.BusinessException;
import java.util.List;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
Expand All @@ -15,6 +13,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
Expand All @@ -29,9 +28,14 @@ public Resume saveResume(Resume resume) {
}

// 이력서 개별 조회
@Transactional
public Resume getResume(Long resumeId) {
return resumeRepository.findById(resumeId)
Resume resume = resumeRepository.findById(resumeId)
.orElseThrow(ResumeNotFoundException::new);

// 이력서 조회수 증가
resume.increaseViewCount();
return resume;
}

// 유저 이름으로 이력서 조회
Expand All @@ -45,18 +49,9 @@ public Page<Resume> searchByTages(ResumeSearchRequest req, Pageable pageable) {
}


public Page<Resume> getResumePage(Pageable pageable) {
public Slice<Resume> getResumePage(Pageable pageable) {
// 페이지네이션을 적용하여 레포지토리에서 데이터를 가져옴
Page<Resume> resumes = resumeRepository.findAll(pageable);

// 첫 번째 Resume 객체를 가져옴 (예시로 첫 번째 요소를 변환)
Resume resume = resumes.getContent().isEmpty() ? null : resumes.getContent().get(0);

// Resume가 없을 경우 빈 결과를 처리
if (resume == null) {
throw new BusinessException(ErrorCode.RESUME_NOT_FOUND);
}

Slice<Resume> resumes = resumeRepository.findResumesByDeletedAtIsNull(pageable);
return resumes;
}

Expand Down