ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 동의어 등록 테스트 ( nori / Elasticsearch v6.5.4)
    검색/ElasticSearch 2021. 8. 26. 14:22
    반응형

    동의어 사전이 적용되는 시점

    Tokenizer를 통해 형태소 분석이 끝난 후에 Token Filters에 정의한 순서 대로 사전이 적용된다.

    동의어 등록

    ELS_HOME/config/synonyms.txt
    동의어는 하나의 규칙당 한 줄식 입력해야 하며 파일은 UTF8로 인코딩 되어야한다.

    에어프라이어,에어플라이어,애어프라이어,애어플라이어
    에이아이,인공지능
    대한민국,우리나라,한국
    한국,코리아,korea
    아름다움,멋=>뿜뿜

    동의어 등록 후에는 _setting 정보를 update하기 위해 indices를 닫았다가 열어야한다.

    POST synonyms_dic_test/_close
    POST synonyms_dic_test/_open

    이미 색인된 데이터에 사전을 반영하기 위해서는 재색인을 해야한다

    동의어 적용 테스트

    기존 인덱스 삭제

    DELETE synonyms_dic_test

    인덱스 생성

    PUT synonyms_dic_test/
    {
      "mappings": {
        "product": {
          "properties": {
            
            "product_sub_title": {
              "type": "text",
              "analyzer": "korean"
            },
            "product_title": {
              "type": "text",
              "analyzer": "korean"
            }
          }
        }
      },
      "settings": {
        "index": {
          "number_of_shards": "3",
          "refresh_interval" : "-1",
          "analysis": {
            "filter": {
              "stop_filter": {
                "type": "stop",
                "stopwords_path": "stopwords.txt"
              },
              "synonym": {
                "type": "synonym",
                "synonyms_path": "dic/synonyms.txt",
                "updateable": "true"
              }
            },
            "char_filter": {
              "decimal_mark_filter": {
                "pattern": "(\\d+),(?=\\d)",
                "type": "pattern_replace",
                "replacement": "$1 "
              }
            },
            "analyzer": {
              "korean": {
                "filter": [
                  "lowercase",
                  "synonym",
                  "stop_filter"
                ],
                "type": "custom",
                "tokenizer": "korean_default_tokenizer"
              },
              "category_seq_analyzer": {
                "char_filter": [
                  "decimal_mark_filter"
                ],
                "tokenizer": "standard"
              }
            },
            "tokenizer": {
              "korean_default_tokenizer": {
                "type": "nori_tokenizer",
                "user_dictionary": "userdict_ko.txt",
                "decompound_mode": "discard"
              }
            }
          },
          "number_of_replicas": "1"
        }
      }
    }

    테스트 데이터 삽입

    PUT synonyms_dic_test/product/1
    {
      "product_title":"대한민국에 오신것을 환영합니다."
    }
    PUT synonyms_dic_test/product/2
    {
      "product_title":"우리나라는 강산이 어우러져 자연의 아름다움을 느낄 수 있습니다."
    }
    PUT synonyms_dic_test/product/3
    {
      "product_title":"한국의 멋"
    }
    PUT synonyms_dic_test/product/4
    {
      "product_title":"korea는 내나라"
    }
    PUT synonyms_dic_test/product/5
    {
      "product_title":"우리나라의 자랑"
    }
    PUT synonyms_dic_test/product/6
    {
      "product_title":"먼지가 뿜뿜"
    }

    검색 테스트 1

    사전 등록

    대한민국,우리나라,한국
    한국,코리아,korea

    검색 : '우리나라'
    결과 : 사전에 등록한 키워드(대한민국,우리나라,한국,코리아,korea)를 포함한 문서가 검색 된다.

    //검색
    GET synonyms_dic_test/product/_search
    {
      "query": {
        "match": {
          "product_title":{
            "query":"우리나라",
          "operator": "and"
          }
        }
      }
    }
    //결과
    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 3,
        "successful" : 3,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : 5,
        "max_score" : 6.9298778,
        "hits" : [
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "5",
            "_score" : 6.9298778,
            "_source" : {
              "product_title" : "우리나라의 자랑"
            }
          },
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "2",
            "_score" : 4.0648756,
            "_source" : {
              "product_title" : "우리나라는 강산이 어우러져 자연의 아름다움을 느낄 수 있습니다."
            }
          },
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "3",
            "_score" : 2.2562294,
            "_source" : {
              "product_title" : "한국의 멋"
            }
          },
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "1",
            "_score" : 1.6988081,
            "_source" : {
              "product_title" : "대한민국에 오신것을 환영합니다."
            }
          },
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "4",
            "_score" : 0.44839138,
            "_source" : {
              "product_title" : "korea는 내나라"
            }
          }
        ]
      }
    }

    검색 테스트 2

    사전 등록

    아름다움,멋=>뿜뿜

    검색 : ‘아름다움’
    결과 : 사전에 등록한 키워드(아름다움,멋=>뿜뿜) 대로 ‘아름다움’ or ‘멋' 으로 검색시에 ‘아름다움, 멋, 뿜뿜’을 포함한 문서가 검색 된다.

    //검색
    GET synonyms_dic_test/product/_search
    {
      "query": {
        "match": {
          "product_title":{
            "query":"아름다움",
          "operator": "and"
          }
        }
      }
    }
    //결과
    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 3,
        "successful" : 3,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : 3,
        "max_score" : 2.5682926,
        "hits" : [
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "6",
            "_score" : 2.5682926,
            "_source" : {
              "product_title" : "먼지가 뿜뿜"
            }
          },
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "3",
            "_score" : 2.3460367,
            "_source" : {
              "product_title" : "한국의 멋"
            }
          },
          {
            "_index" : "synonyms_dic_test",
            "_type" : "product",
            "_id" : "2",
            "_score" : 1.5926098,
            "_source" : {
              "product_title" : "우리나라는 강산이 어우러져 자연의 아름다움을 느낄 수 있습니다."
            }
          }
        ]
      }
    }

    검색 테스트 3
    'B,C,D =>A' 등록 방식을 ‘A=>B,C,D’로 하면 어떤 결과가 나오는지 확인한다.
    (A를 검색 할때 B,C,D문서가 모두 나올까?)

    사전 검색어 결과
    뿜뿜=>아름다움,멋,자랑 뿜뿜 _id:6 (먼지가 뿜뿜)
    _id:2(우리나라는 강산이 어우러져 자연의 아름다움을 느낄 수 있습니다.)
    _id:6, _id:3 (한국의 멋)
    아름다움 _id:6, _id:2
    자랑 _id:6, _id:5(우리나라의 자랑)
    뿜뿜=>멋,자랑,아름다움 뿜뿜 _id:6, _id:2
    뿜뿜=>자랑,아름다움,멋 뿜뿜 _id:6, _id:2
    자랑=>뿜뿜,아름다움,멋 자랑 _id:6, _id:2, _id:5
    자랑=>아름다움,멋,뿜뿜 자랑 _id:6, _id:2, _id:5
    자랑=>멋,아름다움,뿜뿜 자랑 _id:6, _id:2, _id:5
    아름다움=>멋,자랑,뿜뿜 아름다움 _id:6, _id:2
    아름다움=>자랑,뿜뿜,멋 아름다움 _id:6, _id:2

    결론 : 사전을 등록할 때 A=>B,C,D 로 등록을 하면 A로 검색 할 경우 B,C,D중 하나 혹은 두 개가 임으로 매칭되는 것 같지만 규칙은 모르겠다.
    실제로 A 위치에 해당하는 키워드를 _termvectors로 확인해 보면 B,C,D 키워드를 모두 가지고 있다.

    /*
    사전에 '자랑=>멋,아름다움,뿜뿜' 등록 후
    '우리나라의 자랑'이라는 문구가 들어간 _id:5을 termvectors 로 확인 해 보면
    '자랑'이 '뿜','아름답','멋'으로 변환 되어 들어가 있다.
    그리고 '뿜뿜','아름다움','멋'으로 검색 할 경우 '자랑'이 들어간 문서가 함께 결과로 나오지만,
    '자랑'이라는 검색 결과로는 B,C,D 위치 중 어떤 키워드가 들어간 문장이 나올지 예측 할 수없다.
    */
    GET synonyms_dic_test/product/5/_termvectors?
    {
      "fields" : ["product_title"],
      "offsets" : true,
      "payloads" : true,
      "positions" : true,
      "term_statistics" : true,
      "field_statistics" : true
    }
    
    ===
    {
      "_index" : "synonyms_dic_test",
      "_type" : "product",
      "_id" : "5",
      "_version" : 1,
      "found" : true,
      "took" : 0,
      "term_vectors" : {
        "product_title" : {
          "field_statistics" : {
            "sum_doc_freq" : 40,
            "doc_count" : 4,
            "sum_ttf" : 42
          },
          "terms" : {
            "ᄆ" : {
              "doc_freq" : 2,
              "ttf" : 2,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 4,
                  "start_offset" : 6,
                  "end_offset" : 8
                }
              ]
            },
            "나라" : {
              "doc_freq" : 3,
              "ttf" : 3,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 1,
                  "start_offset" : 2,
                  "end_offset" : 4
                }
              ]
            },
            "대한" : {
              "doc_freq" : 2,
              "ttf" : 2,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 0,
                  "start_offset" : 0,
                  "end_offset" : 2
                }
              ]
            },
            "멋" : {
              "doc_freq" : 1,
              "ttf" : 1,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 3,
                  "start_offset" : 6,
                  "end_offset" : 8
                }
              ]
            },
            "민국" : {
              "doc_freq" : 2,
              "ttf" : 2,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 1,
                  "start_offset" : 2,
                  "end_offset" : 4
                }
              ]
            },
            "뿜" : {
              "doc_freq" : 2,
              "ttf" : 4,
              "term_freq" : 2,
              "tokens" : [
                {
                  "position" : 3,
                  "start_offset" : 6,
                  "end_offset" : 8
                },
                {
                  "position" : 4,
                  "start_offset" : 6,
                  "end_offset" : 8
                }
              ]
            },
            "아름답" : {
              "doc_freq" : 2,
              "ttf" : 2,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 3,
                  "start_offset" : 6,
                  "end_offset" : 8
                }
              ]
            },
            "우리" : {
              "doc_freq" : 2,
              "ttf" : 2,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 0,
                  "start_offset" : 0,
                  "end_offset" : 2
                }
              ]
            },
            "의" : {
              "doc_freq" : 3,
              "ttf" : 3,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 2,
                  "start_offset" : 4,
                  "end_offset" : 5
                }
              ]
            },
            "한국" : {
              "doc_freq" : 3,
              "ttf" : 3,
              "term_freq" : 1,
              "tokens" : [
                {
                  "position" : 0,
                  "start_offset" : 0,
                  "end_offset" : 4
                }
              ]
            }
          }
        }
      }
    }

    참고 링크

    *같지만 다른 단어: 동의어로 Elasticsearch의 성능 강화 :
    https://www.elastic.co/kr/blog/boosting-the-power-of-elasticsearch-with-synonyms

    * 동의어 :
    https://esbook.kimjmin.net/06-text-analysis/6.6-token-filter/6.6.3-synonym

     

    반응형
Designed by Tistory.