역 인덱스

Elasticsearch는 역 인덱스(inverted index) 구조를 통해 데이터를 저장한다.

Elasticsearch는 데이터가 늘어나도 찾아가야 할 행이 늘어나는 것이 아니라 역 인덱스가 가리키는 id의 배열값이 추가되는 것 뿐이기 때문에 큰 속도의 저하 없이 빠른 속도로 검색이 가능하다. 이런 역 인덱스를 데이터가 저장되는 과정에서 만들기 때문에 Elasticsearch는 데이터를 입력할 때 저장이 아닌 색인을 한다고 표현한다.

검색 정확도 향상

1-1 이순신의


‘이순신의’로 검색하면 ‘이순’, ‘신의’로 토큰 분리 발생

GET library/_search
{
  "query": {
       "match": {
         "bookName": "이순신의"
       }
  }
}

q02.jpg

term 쿼리를 통해 ‘이순신의’ 자체 키워드를 검색하고, 접두사에 공백을 추가 match_phrase_prefix 쿼리를 날리면 ‘이순신’도 검색된다

GET library/_search
{
  "query":{
    "bool":{
      "should":[
        {"term":{
          "bookName": "이순신의"
        }},
        {"match_phrase_prefix": {
          "bookName": "이순신의 "
        }}
      ]
    }
  }
}

q04.jpg

1-2. 중복 제거


isbn 필드 기준 하나의 doc으로 압축

GET library/_search
{
  "query": {
       "match": {
         "bookName": "동물농장"
       }
  },
    "collapse": {
    "field": "isbn13"
  }
}

검색 속도 향상


public List<LibraryEs> findByBookName(String keyword) {
        Pageable pageable = PageRequest.of(0, 1000);
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("bookName",keyword))
                .should(QueryBuilders.termQuery("bookName.keyword",keyword))
                .should(QueryBuilders.matchPhraseQuery("bookName",keyword));

        NativeSearchQuery nativeSearchQuery= new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
                .withPageable(pageable)
                .build();
        SearchHits<LibraryEs> search = operations.search(nativeSearchQuery, LibraryEs.class);
        List<SearchHit<LibraryEs>> searchHitList = search.getSearchHits();
        List<LibraryEs> list = new ArrayList<>();
        for (SearchHit<LibraryEs> libraryEsSearchHit : searchHitList) {
            list.add(libraryEsSearchHit.getContent());
        }
        return list;
    }