home..

Udemy Elasticsearch - 검색 원리

Elasticsearch Udemy 강의( Complete Guide to Elastticsearch )를 보면서 document에서 document 검색 관련 정리할 내용을 기록한다.

Search Query

search query는 Elasticsearch data streams / indices의 데이터를 요청하는 쿼리를 의미한다.

Search API

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-your-data.html#run-an-es-search

아래는 match 쿼리로 my-index-000001를 탐색하는 요청 예시다.

[ 예시 ] user.id = kimchy인 document를 검색

GET /my-index-000001/_search
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

[ 결과 ] 기본적으로 score가 가장 높은 10개 문서를 가져온다.(문서 갯수는 설정할 수 있음)

{
  "took": 5, 
  "timed_out": false, 
  "_shards": { # sharding에 대한 정보 
    "total": 1, # 전체 shards = 1
    "successful": 1, # 성공 = 1
    "skipped": 0,
    "failed": 0 # 실패 = 1
  },
  "hits": { # 실제 결과에 대한 정보
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.3862942, # score 중 가장 높은 값
    "hits": [ # documents 
      {
        "_index": "my-index-000001",
        "_type": "_doc",
        "_id": "kxWFcnMByiguvud1Z8vC",
        "_score": 1.3862942,  # relevance score
        "_source": { 
          "@timestamp": "2099-11-15T14:12:12",
          "http": {
            "request": {
              "method": "get" 
            },
            "response": {
              "bytes": 1070000,
              "status_code": 200
            },
            "version": "1.1"
          },
          "message": "GET /search HTTP/1.1 200 1070000",
          "source": {
            "ip": "127.0.0.1"
          },
          "user": {
            "id": "kimchy"
          }
        }
      }
    ]
  }
}

Relevance

각 document의 relevance score는 _score로 표시된다. 이 수치가 높을수록 연관성이 높다고 할 수 있다. score는 query clause의 type에 따라 계산되는데 relevance는 full-text field의 내용이 full-text 쿼리문과 얼마나 유사한지를 판단한다.

Similarity - TFIDF

https://www.elastic.co/guide/en/elasticsearch/guide/current/relevance-intro.html 표준 유사도 측정은 TF/IDF를 기준으로 한다. _score 계산 과정은 explain을 옵션으로 설정함으로써 파악할 수 있다.

GET /_search?explain 
{
   "query"   : { "match" : { "tweet" : "honeymoon" }}
}

아래와 같이 _explanation에 각 entry는 어떤 계산이 포함되었는지를 설명한다.

"_explanation": { 
   "description": "weight(tweet:honeymoon in 0)
                  [PerFieldSimilarity], result of:",
   "value":       0.076713204, # 계산값
   "details": [
      {
         "description": "fieldWeight in 0, product of:",
         "value":       0.076713204,
         "details": [ 
            {  # Term Frequency
               "description": "tf(freq=1.0), with freq of:",
               "value":       1,
               "details": [
                  {
                     "description": "termFreq=1.0",
                     "value":       1
                  }
               ]
            },
            { # Inverse document frequency
               "description": "idf(docFreq=1, maxDocs=1)",
               "value":       0.30685282
            },
            { # Field-length norm
               "description": "fieldNorm(doc=0)",
               "value":        0.25,
            }
         ]
      }
   ]
}

요약하면 특정 단어가 해당 문서에서 많이 등장하면서 전체 문서에선 등장 횟수가 적으면 그 문서를 설명하는 핵심 단어라고 할 수 있으므로 연관성이 높다. 하지만 검색하는 대상의 필드의 내용이 길수록 필드에 대한 연관성이 적으므로 전체적으로 수치를 살펴볼 필요가 있다.

왜 해당 문서가 matched인지는 /index/type/id/_explain에 요청하여 확인한다.

GET /us/tweet/12/_explain
{
   "query" : {
      "bool" : {
         "filter" : { "term" :  { "user_id" : 2           }},
         "must" :  { "match" : { "tweet" :   "honeymoon" }}
      }
   }
}

위와 같이 요청하여,

"failure to match filter: cache(user_id:[2 TO 2])"

결과를 확인하면 user_id로 인해 matching되지 않음을 알 수 있다.

Similarity - BM25

최근에는 BM25를 적용하여 score를 계산한다.

© 2024 Yujin Lee   •  Powered by Soopr   •  Theme  Moonwalk