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.

더 알아보기