고민중인 것
1. 검색 기능을 구현시 어떤 식으로 구현할 것인가 고민이다.
채용 공고를 키워드로 검색하여 해당하는 채용공고들을 보여줘야 하는데
현재 채용공고 테이블에는 4개의 컬림이 있고, 회사 테이블에는 3개의 컬럼이 있다.
간단하게 생각나는 방법으로는 단순하게 모든 컬럼에서 해당 키워드가 있는지 검색을 하는 것이다.
(채용 포지션, 요구 스킬, 채용 보상금, 채용 내용, 회사명, 국가, 지역)
테이블에 데이터가 몇건 없다면 사실 큰 문제가 없으리라 생각하지만 데이터가 엄청나게 많다면 이는 분명 문제가 될 것이라고 생각한다.
그 다음으로 생각한 것이
채용 포지션, 요구 스킬, 채용 보상금, 채용 내용, 회사명, 국가, 지역 모두를 하나로 합쳐서 하나의 컬럼(예를 들면 키워드라는 이름의 컬럼)을 만들어 해당 컬럼에서 유저가 검색한 키워드가 포함되어 있는지를 검색하는 것이다.
모든 컬럼을 돌지 않고 하나의 컬럼에만 의존하기 때문에 이전보다는 좋은 방법이지 않을까? 하고 생각은 하고 있다.
그 다음은 조금 시간이 걸리더라도 엘라스틱서치 혹은 루씬을 사용하는 것이다.
이건 너무 과한것 같아 일단은 생각만 하고 있다.
다른 좋은 방법이 없는지 좀 더 찾아봐야겠다.
-------
알아낸 몇가지 방법 중 Example Matcher와 JPA Specification 이라는 것을 알게 되었다.
1. ExampleMatcher
@Override
public Page<EmployeeProjectView> findEmployeeProjectsExampleMatcher(EmployeeRequestDTO employeeRequestDTO)
{
/* Build Search object */
EmployeeProjectView employeeProjectView=new EmployeeProjectView();
employeeProjectView.setEmployeeId(employeeRequestDTO.getEmployeeId());
employeeProjectView.setLastName(employeeRequestDTO.getFilterText());
employeeProjectView.setFirstName(employeeRequestDTO.getFilterText());
try
{
employeeProjectView.setProjectId(Long.valueOf(employeeRequestDTO.getFilterText()));
employeeProjectView.setProjectBudget(Double.valueOf(employeeRequestDTO.getFilterText()));
}
catch (Exception e)
{
log.debug("Supplied filter text is not a Number");
}
employeeProjectView.setProjectName(employeeRequestDTO.getFilterText());
employeeProjectView.setProjectLocation(employeeRequestDTO.getFilterText());
/* Build Example and ExampleMatcher object */
ExampleMatcher customExampleMatcher = ExampleMatcher.matchingAny()
.withMatcher("firstName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
.withMatcher("lastName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
.withMatcher("projectId", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
.withMatcher("projectName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
.withMatcher("projectLocation", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
.withMatcher("projectBudget", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase());
Example<EmployeeProjectView> employeeExample= Example.of(employeeProjectView, customExampleMatcher);
/* Get employees based on search criteria*/
return employeeProjectViewRepository.findAll(employeeExample, PageRequest.of(employeeRequestDTO.getCurrentPageNumber(),
employeeRequestDTO.getPageSize(), Sort.by(employeeRequestDTO.getSortColumnName()).descending()));
}
2. JPA Specification
private Specification<EmployeeProjectView> getSpecification(EmployeeRequestDTO employeeRequestDTO)
{
//Build Specification with Employee Id and Filter Text
return (root, criteriaQuery, criteriaBuilder) ->
{
criteriaQuery.distinct(true);
//Predicate for Employee Id
Predicate predicateForEmployee = criteriaBuilder.equal(root.get("employeeId"), employeeRequestDTO.getEmployeeId());
if (isNotNullOrEmpty(employeeRequestDTO.getFilterText()))
{
//Predicate for Employee Projects data
Predicate predicateForData = criteriaBuilder.or(
criteriaBuilder.like(root.get("firstName"), "%" + employeeRequestDTO.getFilterText() + "%"),
criteriaBuilder.like(root.get("lastName"), "%" + employeeRequestDTO.getFilterText() + "%"),
criteriaBuilder.like(root.get("projectId").as(String.class), "%" + employeeRequestDTO.getFilterText() + "%"),
criteriaBuilder.like(root.get("projectName"), "%" + employeeRequestDTO.getFilterText() + "%"),
criteriaBuilder.like(root.get("projectBudget").as(String.class), "%" + employeeRequestDTO.getFilterText() + "%"),
criteriaBuilder.like(root.get("projectLocation"), "%" + employeeRequestDTO.getFilterText() + "%"));
//Combine both predicates
return criteriaBuilder.and(predicateForEmployee, predicateForData);
}
return criteriaBuilder.and(predicateForEmployee);
};
}
두가지 방법 모두 내가 검색하고자 하는 컬럼을 미리 지정한 다음 그 조건으로 쿼리를 만들어 주는 기능으로 보인다.
장점이라면 복잡한 쿼리를 내가 직접 만들 필요가 없다는 것인데
단점이라면 역시 컬럼이 추가되거나 변경 되었을때 조금 불편할 수 있다는 것이다.
다만 현재로서는 위 두가지 방법이 가장 좋아 보인다.
물론 내가 직접 @Query 어노테이션을 사용하여 검색 쿼리를 작성 할 수도 있지만 우선 위의 두 방법을 사용해보고 정하면 좋을 것 같다.
'Java 웹 프로그래밍' 카테고리의 다른 글
[원티드 프리온보딩] 개발하면서 든 생각. 외래키가 꼭 필요한가 (0) | 2023.10.09 |
---|---|
[원티드 프리온보딩] 회사의 채용 공고 List (0) | 2023.10.08 |
[원티드 프리온보딩] Service와 ServiceImpl (0) | 2023.10.07 |
[원티드 프리온보딩] 데이터 조회시 없는 경우 404를 내줄것인가 빈 JSON데이터를 내줄것인가. (0) | 2023.10.07 |
15일차 강의 후기 (0) | 2022.02.07 |