ElasticSearch score 커스터마이징

By | 2020년 6월 21일
Table of Contents

ElasticSearch score 커스터마이징

ES 는 기본값으로 BM25 알고리즘을 이용해 score 를 계산합니다.

BM25 알고리즘

검색키워드의 빈도수, 문서상의 키워드의 빈도수, 문서의 크기 등을 기준으로 score 를 산정합니다.

TF(Term Frequency)

문서 내에서 자주 등장하는 단어(Term) 에 가중치를 높게 부여합니다.

IDF(Inverse Document Frequency)

많은 문서에서 등장하는 단어(Term) 의 가중치는 낮추고, 일부 문서에서만 등장하는 단어(Term) 에 대해 높은 가중치를 부여합니다.

문서의 종류를 가리지 않고 자주 등장하는 단어는 별 의미없는 흔한 단어일 가능성이 높기 때문입니다.

Field-length norm

두개 이상의 문서에서 동일한 키워드가 동일한 빈도수로 등장한다고 가정할 때, 문서의 길이가 작은 문서에 더 높은 가중치를 부여합니다.

score 커스터마이징

하지만 쇼핑몰에서는 검색어의 빈도수만 가지고 score 를 산정할 수 없습니다.

간단하게 아이폰 이라는 키워드와 기존 고객들이 검색 후 클릭한 수, 구매한 수가 높은 상품에 우선순위를 더 부여할 필요가 있습니다.

아래에서 function_score 를 이용해 위 기능을 구현해 봅니다.

참조 사이트

기본설정

여기 에 설명된 서버설정을 기초로 수정합니다.

테이블 준비

CREATE DATABASE db_test DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;

USE db_test;

DROP TABLE IF EXISTS items;

CREATE TABLE items (
    itemid BIGINT(20) UNSIGNED NOT NULL,
    PRIMARY KEY (itemid),
    UNIQUE KEY unique_id (itemid),
    itemname VARCHAR(128) NOT NULL,
    viewKeywords VARCHAR(2048) NOT NULL,
    buyKeywords VARCHAR(2048) NOT NULL,
    lastupdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    regdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO items (itemid, itemname, viewKeywords, buyKeywords)
VALUES (1, '블랙 아이폰 케이스', '아이폰 케이스', '');

INSERT INTO items (itemid, itemname, viewKeywords, buyKeywords)
VALUES (2, '블랙 갤럭시 케이스', '갤럭시', '갤럭시');

INSERT INTO items (itemid, itemname, viewKeywords, buyKeywords)
VALUES (3, '핑크 아이폰 케이스', '아이폰', '');

INSERT INTO items (itemid, itemname, viewKeywords, buyKeywords)
VALUES (4, '화이트 갤럭시 케이스', '', '');

INSERT INTO items (itemid, itemname, viewKeywords, buyKeywords)
VALUES (5, '래드 아이폰 케이스', '케이스', '아이폰');

조회키워드와 구매키워드를 데이타로 입력해 줍니다.

인덱스 준비

curl -XDELETE http://localhost:9200/items?pretty

curl -XPUT http://localhost:9200/items?pretty -H 'Content-Type: application/json' -d '{
  "settings" : {
    "index":{
      "analysis":{
        "analyzer":{
          "korean":{
            "type":"custom",
            "tokenizer":"seunjeon_default_tokenizer",
            "filter" : ["synonym", "stopword", "lowercase"]
          }
        },
        "filter" : {
          "synonym" : {
            "type" : "synonym",
            "synonyms_path" : "synonyms.txt"
          },
          "stopword" : {
            "type" : "stop",
            "stopwords_path" : "stopwords.txt"
          }
        },
        "tokenizer": {
          "seunjeon_default_tokenizer": {
            "index_eojeol": "true",
            "user_dict_path": "user_dict.csv",
            "index_poses": [
                "UNK", "EP", "I", "J", "M",
                "N", "SL", "SH", "SN", "VCP",
                "XP", "XS", "XR"
            ],
            "decompound": "true",
            "type": "seunjeon_tokenizer"
          }
        }
      }
    }
  },
  "mappings" : {
    "_doc" : {
      "properties" : {
        "itemid" : {
          "type" : "integer"
        },
        "itemname" : {
          "type" : "text",
          "analyzer": "korean"
        },
        "viewKeywords" : {
          "type" : "text",
          "analyzer": "korean"
        },
        "buyKeywords" : {
          "type" : "text",
          "analyzer": "korean"
        },
        "lastupdate" : {
          "type" : "date"
        },
        "regdate" : {
          "type" : "date"
        }
      }
    }
  }
}'

가중치를 부여한 검색

curl -X GET "localhost:9200/items/_search?pretty" -H 'Content-Type: application/json' -d'{
    "query": {
        "function_score": {
            "query": { "match": { "itemname": "아이폰 케이스" } },
            "boost": "5",
            "functions": [
                {
                    "filter": { "match": { "viewKeywords": "아이폰 케이스" } },
                    "random_score": {},
                    "weight": 23
                },
                {
                    "filter": { "match": { "buyKeywords": "아이폰 케이스" } },
                    "weight": 42
                }
            ],
            "max_boost": 42,
            "score_mode": "max",
            "boost_mode": "multiply",
            "min_score" : 0
        }
    }
}'

2 thoughts on “ElasticSearch score 커스터마이징

답글 남기기