본문 바로가기
스프링 쇼핑몰 만들어보기

검색 기능 - index

by hoshi03 2024. 5. 8.

아이템 목록을 가져오는 기능을 만들어보자

 

폼에 serachText로 찾고 싶은 아이템 이름을 넘겨주고

<form action="/search" method="GET">
    <input name="searchText" style="display: inline">
    <button>검색</button>
</form>

 

리포지토리에서는 해당 이름을 포함한 아이템들 리스트를 반환하게 해서

List<Item> findAllByTitleContains(String title);

 

컨트롤러에서는 찾은걸 반환하게 했다

@GetMapping("/search")
String postSearch(@RequestParam String searchText, Model model){
    List<Item> itemList = itemRepository.findAllByTitleContains(searchText);
    if (!itemList.isEmpty()){
        model.addAttribute("items", itemList);
    }
    return "search.html";
}

 

나오긴 나오는데 이대로 쓰면 where item.title like ~ 같은 쿼리로 조회하는거라 아이템이 많으면 느리다

인덱스를 이용해서 빠르게 조회되게 만들자

인덱스 - 정렬해서 복사해둔 컬럼 - 이분탐색으로 조회 가능

 

인덱스를 만들려면 엔티티에 가서 아래처럼 어노테이션을 추가한다

멀티 컬럼 인덱스나 인덱스 여러개도 추가 가능하다

@Table(indexes = @Index(columnList = "title", name = "itemTitleIDX"))

 

 

이런 형태로 인덱스 여러개 작성 가능하다

@Entity
@Table(indexes = {
  @Index(name = "인덱스이름작명", columnList = "인덱스만들컬럼명1"),
  @Index(name = "인덱스이름작명", columnList = "인덱스만들컬럼명2")
})

 

컨트롤러에 만들어둔 이 쿼리문은 인덱스가 있어도 where like %~% 형태의 쿼리를 쓰기에

풀텍스트 인덱스를 작성해야된다

List<Item> itemList = itemRepository.findAllByTitleContains(searchText);

 

풀텍스트 인덱스 - 문장에서 단어만 빼서 원래 어느 문장에 있었는지와 함께 저장하는 인덱스

한국어는 단어단위로 쪼개면 조사 등 때문에 너무 잘게 쪼개져서

n글자씩 추출해서 인덱스를 만드는 n-gram parser를 사용한다

 

item 테이블에 title 컬럼에 대해서 풀텍스트 인덱스를 생성한다

create fulltext index fulltext_index on item(title) with parser ngram;

 

• JPA에 쌩 쿼리 사용하는방법

@Query(value = "sql~~", nativeQuery = true)로 하면 가능

?1 ?2 .. 형태로 파라미터도 넣을  수 있다

@Query(value = "select * from item where id = ?1", nativeQuery = true)
Item rawQuery1(Long num);

 

풀텍스트 쿼리를 사용해서 title이 against에 들어간 변수가 포함되면 가져오는 쿼리문

select * from item where match(title) against(?1)

 

그걸 이용한 쌩쿼리 함수

@Query(value = "select * from item where match(title) against(?1)", nativeQuery = true)
List<Item> rawQuery1(String searchText);

 

위에서 만든 함수를 이용해서 특정 단어가 포함된 글을 가져왔다

@GetMapping("/search")
String postSearch(@RequestParam String searchText, Model model){
    List<Item> itemList = itemRepository.rawQuery1(searchText);
    if (!itemList.isEmpty()){
        model.addAttribute("items", itemList);
    }
    return "search.html";
}

 

match agains를 이용해서 가져오면 단어가 많이 포함된 순으로 자동으로 정렬해서 가져온다!