본문 바로가기
Computer Science

Elastic Search 톺아보기 #3

by Bloofer 2023. 4. 12.

 

문장 검색하기

Elastic Stack에서는 match_phrase 쿼리를 사용하여 정확한 문장 검색을 할 수 있다. 이를 사용하면 원하는 구문에 대한 정확한 쿼리를 받을 수 있다. 또한, multi_match 쿼리를 사용하여 여러 필드에서 한 번에 검색할 수 있으며, 필드 당 가중치를 다르게 주어 원하는 결과를 얻을 수 있다. Bool Query를 사용하여 여러 쿼리를 조합하여 검색할 수도 있다.

 

이러한 문장 검색에 사용되는 쿼리들을 실제 프랙티스에서는 어떻게 적용할 수 있는지 확인해보자.

먼저, 뉴스 헤드라인 데이터셋에서 에드 시런의 "Shape of you"를 검색하는 시나리오를 상상해보자.

 

GET news_headlines/_search
{
  "query": {
    "match": {
      "headline": {
        "query": "Shape of you"
      }
    }
  }
}

 

위 쿼리를 실행한 결과는 아래와 같다.

 

 

검색결과 문서는 무려 1만개나 나온다(실제 결과는 threshold를 넘어선 그보다 많을 것이다). 하지만, 이 쿼리는 "Shape of you"의 단어를 각각 포함하는 헤드라인을 결과로 반환하기 때문에 정말 원하는 데이터는 이 중에 1%도 되지 않는다.

 

 

match_phrase 쿼리 사용하기

이때 사용하는 것이 match_phrase 쿼리이다. match_phrase 쿼리를 사용하면 우리가 원하는 문장에 대한 정확한 검색을 할 수 있다.

 

GET news_headlines/_search
{
  "query": {
    "match_phrase": {
      "headline": {
        "query": "Shape of You"
      }
    }
  }
}

 

이때 쿼리의 대상은 "match"가 아니라 "match_phrase"가 된다.

 

 

이제 쿼리 결과는 문서 3개만 반환하고, 결과에는 정확하게 원했던 에드 시런의 "Shape of you"에 대한 헤드라인 문서들만 포함되어 있다.

 

 

여러 필드에 대해 매치 쿼리 검색

쿼리를 수행할 때 항상 엘라스틱은 사용자가 원하는 쿼리의 의도나 컨텍스트를 알 수 없다. 이는 사용자가 검색할 때 검색대상 쿼리에 대한 필드 옵션을 추가하여 디자인하여야 한다.

예를 들어, "Michelle Obama"에 대해 검색하는데 뉴스의 헤드라인, 작가 또는 내용에서 해당 단어를 포함한 검색결과를 보고 싶다고 하자.

 

GET news_headlines/_search
{
  "query": {
    "multi_match": {
      "query": "Michelle Obama",
      "fields": [
        "headline",
        "short_description",
        "authors"
      ]
    }
  }
}

 

위 쿼리를 사용하여 아래와 같은 결과를 얻을 수 있다.

 

 

그러나 여기서 문제는 검색한 결과가 미셸 오바마에 대한 내용이 아닌것이다!

수행한 쿼리 결과에 해당 단어를 포함하지만 사실 다른 내용인 것이 문제이다.

 

그러면 여기서 원하는 결과를 얻기 위해 쿼리를 어떻게 바꾸어야 할까?

여기서 적용되는 아이디어는 각 필드별로 가중치를 줘서 정렬하는 것이다! Per-field boosting

 

 

Per-field boosting

Per-field boosting은 동일한 쿼리 결과를 반환하지만, 반환하는 문서들의 순위를 가중치별로 조절한다. 각 필드별로 부스팅 된 가중치에 따라 검색결과에서 원하는 문서를 먼저 확인해볼 수 있는 것이다.

 

GET news_headlines/_search
{
  "query": {
    "multi_match": {
      "query": "Michelle Obama",
      "fields": [
        "headline^2",
        "short_description",
        "authors"
      ]
    }
  }
}

 

위 쿼리에서 "headline^2"을 사용하여 헤드라인 필드에 미셸 오바마를 포함한 헤드라인에 2배 가중치를 줄 수 있다.

 

 

이제 검색결과 수는 동일하지만, 문서들의 순위가 바뀐다. 결과적으로 보고싶었던 문서들 우선으로 쿼리 결과를 확인할 수 있다.

 

 


multi-match query에 phrase 타입 추가하기

multi-match query로 하나 이상의 필드에서 여러 개의 검색어를 가지고 검색을 할 수 있다. multi-match query로 위의 예시들처럼 여러 필드를 동시에 검색하거나 필드별로 가중치를 다르게 설정할 수도 있다. 

 

multi-match query도 일반 match query와 동일하게 원하는 문장에 대해 검색이 가능하다. 예를 들어, party planning이라는 키워드로 멀티매치 쿼리 검색시 대부분 원하는 결과, 그러나 party, planning이 따로 검색되어 정치 기사가 포함된다.

 

GET news_headlines/_search
{
  "query": {
    "multi_match": {
      "query": "party planning",
      "fields": [
        "headline^2",
        "short_description"
      ],
      "type": "phrase"
    }
  }
}

 

이런 결과들을 매치 타입을 "phrase"로 지정하여 원하는 결과를 필터링이 가능하다.

 

 

Bool Query

Bool Query는 여러 개의 쿼리를 조합하여 더 복잡한 검색을 수행할 수 있다.

Bool Query에서 제공되는 필드는 아래의 4종류이다.

 

  1. must: 검색 결과에 포함되어야 하는 쿼리
  2. must_not: 검색 결과에 포함되면 안되는 쿼리
  3. should: 검색 결과에 포함될 수 있는 쿼리
  4. filter: 검색 결과를 필터링하는 쿼리

 

이 4개의 필드를 자유롭게 조합하여 원하는 검색 결과를 얻을 수 있다. 예를 들어, "Michelle Obama"라는 구문을 포함하면서 "WEDDINGS" 카테고리를 제외한 검색 결과를 얻으려면 다음과 같은 코드를 사용할 수 있다.

 

GET news_headlines/_search
{
  "query": {
    "bool": {
      "must": {
        "match_phrase": {
          "headline": "Michelle Obama"
         }
        },
       "must_not":[
         {
          "match": {
            "category": "WEDDINGS"
          }
        }
      ]
    }
  }
}

 

모든 쿼리들은 optional하고 이 4개의 쿼리를 조합해서 원하는 검색결과를 찾을 수 있다.

 

 

검색결과 "Michelle Obama"에 대한 정치면에서의 기사들을 좀 더 의도대로 잘 찾아볼 수 있다.