제퍼넷 로고

OpenSearch를 사용하여 악센트 구분 검색 수행

시간

악센트 부호에 구애받지 않는 텍스트 검색이 필요한 경우가 많습니다. 악센트를 구분하지 않음 검색이라고도 함 분음 부호 불가지론 search는 à, è, Ê, ñ 및 ç와 같은 라틴 문자를 포함하거나 포함하지 않을 수 있는 쿼리에 대해 검색 결과가 동일한 곳입니다. 분음 부호는 발음의 차이를 표시하기 위해 악센트가 있는 영어 문자입니다. 최근 몇 년 동안 카페나 프로테제와 같이 분음 부호가 있는 단어가 주류 영어에 스며들었습니다. 글쎄, 터치! OpenSearch에 답이 있습니다!

OpenSearch는 검색 워크로드를 위한 확장 가능하고 유연하며 확장 가능한 오픈 소스 소프트웨어 제품군입니다. OpenSearch는 세 가지 모드로 배포할 수 있습니다. 자체 관리형 오픈 소스 OpenSearch, 관리형 아마존 오픈서치 서비스Amazon OpenSearch 서버리스. 세 가지 배포 모드는 모두 Apache Lucene에 의해 구동되며 Lucene 분석기를 사용하여 텍스트 분석을 제공합니다.

이 게시물에서는 OpenSearch를 사용하여 발음 구별 부호를 처리하여 악센트를 구분하지 않는 검색을 수행하는 방법을 보여줍니다.

솔루션 개요

Lucene 분석기는 문서를 인덱싱하고 검색하는 동안 텍스트를 분석하는 데 사용되는 Java 라이브러리입니다. 이러한 분석기는 토크나이저와 필터로 구성됩니다. 토크나이저는 들어오는 텍스트를 하나 이상의 토큰으로 분할하고 필터는 불필요한 문자를 수정하거나 제거하여 토큰을 변환하는 데 사용됩니다.

OpenSearch는 토크나이저와 필터의 다양한 조합을 구성할 수 있는 사용자 지정 분석기를 지원합니다. 문자 필터, 토크나이저 및 토큰 필터로 구성될 수 있습니다. 분음 부호를 구분하지 않는 검색을 활성화하기 위해 ASCII 폴딩 토큰 필터를 사용하는 사용자 지정 분석기를 구성합니다.

ASCIIFolding은 처음 127개의 ASCII 문자(Basic Latin Unicode 블록)에 없는 영문자, 숫자 및 기호 유니코드 문자를 해당하는 ASCII 문자(있는 경우)로 변환하는 데 사용되는 방법입니다. 예를 들어 필터는 "à"를 "a"로 변경합니다. 이를 통해 검색 엔진은 악센트에 구애받지 않는 결과를 반환할 수 있습니다.

이 게시물에서는 OpenSearch Service에서 지원하는 ASCIIFolding 필터를 사용하여 악센트를 구분하지 않는 검색을 구성합니다. 우리는 분음 부호가 있는 유럽 영화 이름 집합을 수집하고 분음 부호가 있거나 없는 검색 결과를 확인합니다.

사용자 지정 분석기로 인덱스 만들기

먼저 인덱스를 생성합니다. asciifold_movies 맞춤형 분석기로 custom_asciifolding:

PUT /asciifold_movies
{ "settings": { "analysis": { "analyzer": { "custom_asciifolding": { "tokenizer": "standard", "filter": [ "my_ascii_folding" ] } }, "filter": { "my_ascii_folding": { "type": "asciifolding", "preserve_original": true } } } }, "mappings": { "properties": { "title": { "type": "text", "analyzer": "custom_asciifolding", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }
}

샘플 데이터 수집

다음으로 라틴 문자가 포함된 샘플 데이터를 인덱스로 수집합니다. asciifold_movies:

POST _bulk
{ "index" : { "_index" : "asciifold_movies", "_id":"1"} }
{ "title" : "Jour de fête"}
{ "index" : { "_index" : "asciifold_movies", "_id":"2"} }
{ "title" : "La gloire de mon père" }
{ "index" : { "_index" : "asciifold_movies", "_id":"3"} }
{ "title" : "Le roi et l’oiseau" }
{ "index" : { "_index" : "asciifold_movies", "_id":"4"} }
{ "title" : "Être et avoir" }
{ "index" : { "_index" : "asciifold_movies", "_id":"5"} }
{ "title" : "Kirikou et la sorcière"}
{ "index" : { "_index" : "asciifold_movies", "_id":"6"} }
{ "title" : "Señora Acero"}
{ "index" : { "_index" : "asciifold_movies", "_id":"7"} }
{ "title" : "Señora garçon"}
{ "index" : { "_index" : "asciifold_movies", "_id":"8"} }
{ "title" : "Jour de fete"}

인덱스 쿼리

이제 우리는 asciifold_movies 라틴 문자가 있거나 없는 단어에 대한 색인.

첫 번째 쿼리는 악센트 문자를 사용합니다.

GET asciifold_movies/_search
{
  "query": {
    "match": {
      "title": "fête"
    }
  }
}

두 번째 쿼리는 악센트 표시 없이 동일한 단어의 철자를 사용합니다.

GET asciifold_movies/_search
{
  "query": {
    "match": {
      "title": "fete"
    }
  }
}

이전 쿼리에서 검색어 "fête" 및 "fete"는 동일한 결과를 반환합니다.

{ "took": 10, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 0.7361701, "hits": [ { "_index": "asciifold_movies", "_id": "8", "_score": 0.7361701, "_source": { "title": "Jour de fete" } }, { "_index": "asciifold_movies", "_id": "1", "_score": 0.42547938, "_source": { "title": "Jour de fête" } } ] }
}

마찬가지로 "señora"와 "senora" 또는 "sorcière"와 "sorciere"에 대한 결과를 비교해 보십시오. 악센트를 구분하지 않는 결과는 사용자 정의 분석기와 함께 사용되는 ASCIIFolding 필터 때문입니다.

악센트가 있는 필드에 대한 집계 활성화

악센트를 구분하지 않는 검색을 활성화했으므로 집계가 악센트와 함께 작동하도록 만드는 방법을 살펴보겠습니다.

인덱스에서 다음 쿼리를 시도하십시오.

GET asciifold_movies/_search
{
  "size": 0,
  "aggs": {
    "test": {
      "terms": {
        "field": "title.keyword"
      }
    }
  }
}

다음과 같은 응답을받습니다.

"aggregations" : { "test" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "Jour de fete", "doc_count" : 1 }, { "key" : "Jour de fête", "doc_count" : 1 }, { "key" : "Kirikou et la sorcière", "doc_count" : 1 }, { "key" : "La gloire de mon père", "doc_count" : 1 }, { "key" : "Le roi et l’oiseau", "doc_count" : 1 }, { "key" : "Señora Acero", "doc_count" : 1 }, { "key" : "Señora garçon", "doc_count" : 1 }, { "key" : "Être et avoir", "doc_count" : 1 } ] } }

노멀라이저를 사용하여 악센트를 구분하지 않는 집계 만들기

이전 예에서 집계는 "Jour de fête"에 대한 버킷과 "Jour de fete"에 대한 버킷의 두 가지 버킷을 반환합니다. 분음 부호에 관계없이 집계를 사용하여 필드에 대해 하나의 버킷을 생성할 수 있습니다. 이것은 노멀라이저 필터를 사용하여 달성됩니다.

노멀라이저는 문자 및 토큰 필터의 하위 집합을 지원합니다. 기본값만 사용하는 노멀라이저 필터는 언어 독립적인 검색 방식으로 유니코드 텍스트를 표준화하여 유니코드에서 동일한 문자의 다양한 형식을 표준화하고 분음 부호에 구애받지 않는 집계를 허용하는 간단한 방법입니다.

노멀라이저를 포함하도록 인덱스 매핑을 수정해 보겠습니다. 이전 색인을 삭제한 후 다음 매핑으로 새 색인을 만들고 동일한 데이터세트를 수집합니다.

PUT /asciifold_movies
{
  "settings": {
    "analysis": {
      "analyzer": {
        "custom_asciifolding": {
          "tokenizer": "standard",
          "filter": [
            "my_ascii_folding"
          ]
        }
      },
      "filter": {
        "my_ascii_folding": {
          "type": "asciifolding",
          "preserve_original": true
        }
      },
      "normalizer": {
        "custom_normalizer": {
          "type": "custom",
          "filter": "asciifolding"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "custom_asciifolding",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256,
            "normalizer": "custom_normalizer"
          }
        }
      }
    }
  }
}

동일한 데이터 세트를 수집한 후 다음 쿼리를 시도하십시오.

GET asciifold_movies/_search
{
  "size": 0,
  "aggs": {
    "test": {
      "terms": {
        "field": "title.keyword"
      }
    }
  }
}

다음 결과를 얻습니다.

"aggregations" : {
    "test" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Jour de fete",
          "doc_count" : 2
        },
        {
          "key" : "Etre et avoir",
          "doc_count" : 1
        },
        {
          "key" : "Kirikou et la sorciere",
          "doc_count" : 1
        },
        {
          "key" : "La gloire de mon pere",
          "doc_count" : 1
        },
        {
          "key" : "Le roi et l'oiseau",
          "doc_count" : 1
        },
        {
          "key" : "Senora Acero",
          "doc_count" : 1
        },
        {
          "key" : "Senora garcon",
          "doc_count" : 1
        }
      ]
    }
  }

이제 결과를 비교하고 용어 "Jour de fête" 및 "Jour de fete"가 있는 집계가 doc_count=2인 하나의 버킷으로 롤업되는 것을 볼 수 있습니다.

요약

이 게시물에서는 검색 토큰에 대해 ASCII 폴딩을 수행하고 집계에 대한 키워드 필드를 정규화하도록 인덱스 매핑을 설계하여 악센트를 구분하지 않는 검색 및 집계를 활성화하는 방법을 보여주었습니다. OpenSearch 쿼리 DSL을 사용하여 다양한 검색 기능, 구조화 및 비구조화 검색 애플리케이션을 위한 유연한 기반을 제공합니다. Open Source OpenSearch 커뮤니티는 또한 자연어 처리, 기계 학습 알고리즘, 사용자 정의 사전 및 다양한 기타 플러그인을 지원할 수 있도록 제품을 확장했습니다.

이 게시물에 대한 피드백이 있으면 댓글 섹션에 제출하십시오. 이 게시물에 대해 질문이 있는 경우 다음에서 새 스레드를 시작하십시오. Amazon OpenSearch 서비스 포럼 or AWS 지원에 문의.


저자에 관하여

아루나 고빈다라주 Amazon OpenSearch 전문 솔루션 설계자이며 많은 상용 및 오픈 소스 검색 엔진과 협력했습니다. 그녀는 검색, 관련성 및 사용자 경험에 열정적입니다. 최종 사용자 신호와 검색 엔진 동작의 상관 관계에 대한 그녀의 전문 지식은 많은 고객이 검색 경험을 개선하는 데 도움이 되었습니다. 그녀가 가장 좋아하는 취미는 뉴잉글랜드 트레일과 산을 하이킹하는 것입니다.

spot_img

최신 인텔리전스

spot_img