Explain API
Explain API
1.0에서 도입
Explain API는 특정 문서가 쿼리와 일치하거나 일치하지 않는 이유에 대한 상세 정보를 반환해요. 이 API는 OpenSearch가 각 검색 결과의 관련성 점수(_score)를 어떻게 계산하는지 이해하는 데 도움을 줘서, 검색 관련성 문제를 디버깅하고 쿼리를 최적화하는 데 필수적인 도구예요.
OpenSearch는 Okapi BM25라는 확률 기반 랭킹 프레임워크로 관련성 점수를 계산해요. Okapi BM25는 Apache Lucene이 쓰는 원래 term frequency/inverse document frequency (TF/IDF) 프레임워크를 기반으로 해요.
Explain API는 리소스와 시간 양쪽 모두 비용이 많이 들어요. 프로덕션 클러스터에서는 트러블슈팅 목적으로만 아껴서 사용하기를 권장해요.
출처: 문서
본문
제한 사항 (Limitations)
Explain API는 search_pipeline 매개변수를 지원하지 않아요. 인라인 또는 명명된 검색 파이프라인을 담은 요청을 보내면 parsing_exception 오류가 발생해요. 이는 모든 쿼리 유형에 적용돼요.
explain에서 검색 파이프라인 프로세서를 사용하려면 Search API에 explain=true 쿼리 매개변수를 제공해요. 하이브리드 쿼리에서 explain을 사용하는 방법은 Hybrid search explain을 참고해요.
엔드포인트 (Endpoints)
GET /{index}/_explain/{id}
POST /{index}/_explain/{id}
경로 매개변수 (Path parameters)
다음 표는 사용 가능한 경로 매개변수예요.
| 매개변수 | 필수 | 데이터 타입 | 설명 |
|---|---|---|---|
id |
필수 | String | 문서 ID예요. |
index |
필수 | String | 검색할 인덱스예요. 단일 인덱스 이름만 지정할 수 있어요. |
쿼리 매개변수 (Query parameters)
인덱스와 문서 ID를 지정해야 해요. 나머지 매개변수는 모두 선택 사항이에요.
| 매개변수 | 타입 | 설명 | 필수 |
|---|---|---|---|
analyzer |
String | q 쿼리 문자열에 사용할 애널라이저예요. q가 사용될 때만 유효해요. |
아니요 |
analyze_wildcard |
Boolean | q 문자열에서 와일드카드·prefix 쿼리를 분석할지 여부예요. q가 사용될 때만 유효해요. 기본값은 false예요. |
아니요 |
default_operator |
String | q 쿼리 문자열의 기본 부울 연산자(AND 또는 OR)예요. q가 사용될 때만 유효해요. 기본값은 OR이에요. |
아니요 |
df |
String | q 문자열에서 필드가 지정되지 않았을 때 검색할 기본 필드예요. q가 사용될 때만 유효해요. |
아니요 |
lenient |
Boolean | OpenSearch가 형식 기반 쿼리 실패(예: 정수에 대해 텍스트 필드 쿼리)를 무시할지 지정해요. 기본값은 false예요. |
아니요 |
preference |
String | 결과를 가져올 샤드를 선호 지정해요. 사용 가능한 옵션은 로컬 할당된 샤드 복제본에서 결과를 가져오라고 알려주는 _local과, 특정 샤드 복제본에 배정된 사용자 지정 문자열 값이에요. 기본적으로 OpenSearch는 explain 작업을 무작위 샤드에서 실행해요. |
아니요 |
q |
String | Lucene 구문의 쿼리 문자열이에요. 사용할 때 analyzer, analyze_wildcard, default_operator, df, stored_fields 매개변수로 쿼리 동작을 설정할 수 있어요. |
아니요 |
stored_fields |
String | 반환할 저장된 필드의 쉼표로 구분된 목록이에요. 생략하면 _source만 반환돼요. |
아니요 |
routing |
String | 작업을 특정 샤드로 라우팅하는 데 사용하는 값이에요. | 아니요 |
_source |
String | 응답 본문에 _source 필드를 포함할지 여부예요. 유효한 값은 true(전체 _source 포함), false(_source 제외), 쿼리 응답에 포함할 소스 필드의 쉼표로 구분된 목록이에요. 지정하지 않으면 기본적으로 _source 필드가 Explain API 응답에 반환되지 않아요. |
아니요 |
_source_excludes |
String | 쿼리 응답에서 제외할 소스 필드의 쉼표로 구분된 목록이에요. | 아니요 |
_source_includes |
String | 쿼리 응답에 포함할 소스 필드의 쉼표로 구분된 목록이에요. | 아니요 |
요청 본문 필드 (Request body fields)
요청 본문에는 지정된 문서에 대해 설명할 쿼리가 들어 있어요. 다음 표는 사용 가능한 요청 본문 필드예요.
| 필드 | 데이터 타입 | 설명 |
|---|---|---|
query |
Object | 문서에 대해 실행할 쿼리예요. Search API와 같은 쿼리 구문을 사용해요. 쿼리 유형에 대한 자세한 내용은 Query DSL을 참고해요. |
예시: match 쿼리 설명하기 (Explaining a match query)
다음 예시는 products 인덱스의 문서 1이 name 필드에서 "computer"라는 용어에 대해 쿼리와 일치하는 이유를 설명해요:
POST /products/_explain/1
{
"query": {
"match": {
"name": "computer"
}
}
}
Python 클라이언트로는 이렇게 호출해요:
response = client.explain(
id = "1",
index = "products",
body = {
"query": {
"match": {
"name": "computer"
}
}
}
)
예시 응답 (Example response)
Explain API는 문서가 쿼리와 일치하는지 여부와 점수 계산의 상세한 분석을 포함한 응답을 반환해요. 설명에는 BM25 점수 공식 구성 요소인 term frequency(tf), inverse document frequency(idf), 필드 길이 정규화가 포함돼요:
{
"_index": "products",
"_id": "1",
"matched": true,
"explanation": {
"value": 0.31506687,
"description": "weight(name:computer in 0) [PerFieldSimilarity], result of:",
"details": [
{
"value": 0.31506687,
"description": "score(freq=1.0), computed as boost * idf * tf from:",
"details": [
{
"value": 0.6931472,
"description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
"details": [
{
"value": 2,
"description": "n, number of documents containing term",
"details": []
},
{
"value": 4,
"description": "N, total number of documents with field",
"details": []
}
]
},
{
"value": 0.45454544,
"description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
"details": [
{
"value": 1.0,
"description": "freq, occurrences of term within document",
"details": []
},
{
"value": 1.2,
"description": "k1, term saturation parameter",
"details": []
},
{
"value": 0.75,
"description": "b, length normalization parameter",
"details": []
},
{
"value": 2.0,
"description": "dl, length of field",
"details": []
},
{
"value": 2.0,
"description": "avgdl, average length of field",
"details": []
}
]
}
]
}
]
}
}
예시: 쿼리 문자열 매개변수 사용하기 (Using the query string parameter)
요청 본문을 제공하는 대신 q 매개변수로 Lucene 쿼리 문자열 구문을 사용해 쿼리를 지정할 수 있어요. 다음 예시는 문서 1이 "name:laptop" 쿼리 문자열과 일치하는 이유를 설명해요:
GET /products/_explain/1?q=name:laptop
Python 클라이언트로는 이렇게 호출해요:
response = client.explain(
id = "1",
index = "products",
params = { "q": "name:laptop" },
body = { "Insert body here" }
)
응답 본문 필드 (Response body fields)
응답은 문서가 쿼리와 일치하는지 여부와 관련성 점수가 계산된 방법에 대한 상세 정보를 담고 있어요. 다음 표는 응답 본문 필드예요.
| 필드 | 데이터 타입 | 설명 |
|---|---|---|
_index |
String | 문서를 담고 있는 인덱스의 이름이에요. |
_id |
String | 문서 ID예요. |
matched |
Boolean | 문서가 쿼리와 일치하는지 여부예요. true면 문서가 일치하고 관련성 점수가 있어요. false면 문서가 쿼리와 일치하지 않아요. |
explanation |
Object | 점수 계산의 설명이에요. 다음 중첩 필드를 담고 있어요: value(계산된 점수 또는 점수 구성 요소), description(계산에 대한 사람이 읽을 수 있는 설명), details(중첩 계산에 대한 하위 설명 배열). |
explanation.value |
Float | 점수 계산의 숫자 결과예요. 최상위 설명에서는 최종 관련성 점수이고, 중첩 설명에서는 중간 계산 값이에요. |
explanation.description |
String | 수행되는 계산에 대한 설명이에요. BM25 점수에서는 보통 term frequency(tf), inverse document frequency(idf), 정규화 요소 같은 점수 공식 구성 요소를 설명해요. |
explanation.details |
객체 배열 | 점수 계산을 구성 요소로 나누는 중첩 설명 객체 배열이에요. 각 detail 객체는 설명 객체와 같은 구조(value, description, details 필드)를 가져요. |
get |
Object | 문서 메타데이터와 소스 데이터예요. _source 또는 stored_fields 매개변수를 사용할 때만 포함돼요. _seq_no, _primary_term, found, _source 같은 필드를 담고 있어요. |
get._source |
Object | 문서의 원래 JSON 내용이에요. _source 매개변수가 지정될 때만 포함돼요. |
BM25 점수 구성 요소 (BM25 scoring components)
설명 세부 내용에는 다음 BM25 점수 구성 요소가 포함돼요.
| 필드 | 설명 |
|---|---|
idf |
역문서 빈도(inverse document frequency)예요. 인덱스의 모든 문서에서 용어가 얼마나 드물거나 흔한지를 측정해요. log(1 + (N - n + 0.5) / (n + 0.5))로 계산되며, N은 필드가 있는 총 문서 수, n은 용어를 포함한 문서 수예요. 더 드문 용어일수록 IDF 값이 높고 관련성 점수에 더 많이 기여해요. |
tf |
용어 빈도(term frequency)예요. 문서 필드에서 용어가 얼마나 자주 나타나는지 측정해요. freq / (freq + k1 * (1 - b + b * dl / avgdl))로 계산되며, freq는 용어가 나타난 횟수, k1은 용어 포화 매개변수(기본 1.2), b는 길이 정규화 매개변수(기본 0.75), dl은 필드 길이, avgdl은 모든 문서의 평균 필드 길이예요. 더 자주 나타나는 용어가 관련성 점수에 더 기여하지만, 수익 체감이 있어요. |
k1 |
용어 포화(saturation) 매개변수예요. 용어 빈도가 증가할 때 점수가 얼마나 빨리 올라가는지 제어해요. 기본값은 1.2예요. 값이 낮으면 점수가 더 빨리 포화되고, 값이 높으면 용어 빈도가 점수에 더 큰 영향을 미쳐요. |
b |
길이 정규화 매개변수예요. 필드 길이가 점수에 얼마나 영향을 주는지 제어해요. 기본값은 0.75예요. 0이면 길이 정규화를 비활성화하고, 1이면 필드 길이로 완전히 정규화해요. 일치 용어가 있는 짧은 필드가 보통 더 높은 점수를 받아요. |
dl |
문서 필드 길이예요. 이 특정 문서의 필드에 있는 토큰 수예요. |
avgdl |
평균 문서 필드 길이예요. 인덱스의 모든 문서에서 필드의 평균 토큰 수예요. |
boost |
쿼리 부스트 값이에요. 점수에 적용되는 배수예요. 쿼리에 명시적으로 지정하지 않으면 기본 부스트는 1.0이에요. |
최종 관련성 점수는 이 구성 요소들을 곱해 계산돼요: score = boost * idf * tf. 값은 문서를 추가하거나 업데이트할 때 색인 시간에 계산·저장되며, 샤드 수준 통계에 따라 작은 부정확성이 있을 수 있어요.
필요한 권한 (Required permissions)
Security 플러그인을 사용한다면 적절한 권한이 있는지 확인해야 해요: indices:data/read/explain.