Script score 쿼리
Script score 쿼리
스크립트를 사용해 점수 계산을 사용자 지정하려면 script_score 쿼리를 사용해요. 비용이 많이 드는 점수 함수의 경우 script_score 쿼리로 필터링된 반환 문서에만 점수를 계산할 수 있어요.
출처: 문서
본문
스크립트를 사용해 점수 계산을 사용자 지정하려면 script_score 쿼리를 사용해요. 비용이 많이 드는 점수 함수의 경우 script_score 쿼리로 필터링된 반환 문서에 대해서만 점수를 계산할 수 있어요.
예제 (Example)
예를 들어 다음 요청은 문서 하나를 포함하는 인덱스를 생성해요:
PUT testindex1/_doc/1
{
"name": "John Doe",
"multiplier": 0.5
}
match 쿼리를 사용해 name 필드에 John이 포함된 모든 문서를 반환할 수 있어요:
GET testindex1/_search
{
"query": {
"match": {
"name": "John"
}
}
}
응답에서 문서 1의 점수는 0.2876821이에요:
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "testindex1",
"_id": "1",
"_score": 0.2876821,
"_source": {
"name": "John Doe",
"multiplier": 0.5
}
}
]
}
}
이제 문서 점수를 _score 필드의 값에 multiplier 필드의 값을 곱한 것으로 계산하는 스크립트를 사용해 변경해 봐요. 다음 쿼리에서는 문서의 현재 관련성 점수를 _score 변수로, multiplier 값은 doc['multiplier'].value로 접근할 수 있어요:
GET testindex1/_search
{
"query": {
"script_score": {
"query": {
"match": {
"name": "John"
}
},
"script": {
"source": "_score * doc['multiplier'].value"
}
}
}
}
응답에서 문서 1의 점수는 원래 점수의 절반이에요:
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.14384104,
"hits": [
{
"_index": "testindex1",
"_id": "1",
"_score": 0.14384104,
"_source": {
"name": "John Doe",
"multiplier": 0.5
}
}
]
}
}
파라미터 (Parameters)
script_score 쿼리는 다음 최상위 파라미터를 지원해요.
Parameter Data type Description
query | 객체(Object) | 검색에 사용되는 쿼리예요. 필수예요.
script | 객체(Object) | 쿼리가 반환한 문서의 점수를 계산하는 데 사용되는 스크립트예요. 필수예요.
min_score | 실수(Float) | 결과에서 min_score보다 낮은 점수의 문서를 제외해요. 선택이에요.
boost | 실수(Float) | 주어진 배수로 문서 점수를 상향해요. 1.0보다 작은 값은 관련성을 낮추고, 1.0보다 큰 값은 관련성을 높여요. 기본값은 1.0이에요.
script_score 쿼리로 계산된 관련성 점수는 음수가 될 수 없어요.
내장 함수로 점수 계산 사용자 지정
점수 계산을 사용자 지정하려면 내장 Painless 함수 중 하나를 사용할 수 있어요. OpenSearch는 각 함수에 대해 script score 컨텍스트에서 접근할 수 있는 하나 이상의 Painless 메서드를 제공해요. 다음 섹션에 나열된 Painless 메서드는 클래스 이름이나 인스턴스 이름 한정자 없이 직접 호출할 수 있어요. 자세한 내용은 Painless scripting language를 참고하세요.
Saturation (포화) 함수
saturation 함수는 score = value /(value + pivot)으로 계산해요. value는 필드 값이고, pivot은 value가 pivot보다 크면 점수가 0.5보다 크고 작으면 0.5보다 작아지도록 선택돼요. 점수는 (0, 1) 범위예요. saturation 함수를 적용하려면 다음 Painless 메서드를 호출하세요:
double saturation(double
예제 (Example)
다음 예제 쿼리는 articles 인덱스에서 neural search 텍스트를 검색해요. 원래 문서 관련성 점수와 article_rank 값을 결합하며, 이 값은 먼저 saturation 함수로 변환돼요:
GET articles/_search
{
"query": {
"script_score": {
"query": {
"match": { "article_name": "neural search" }
},
"script" : {
"source" : "_score + saturation(doc['article_rank'].value, 11)"
}
}
}
}
Sigmoid (시그모이드) 함수
saturation 함수와 유사하게 sigmoid 함수는 score = value^exp/ (value^exp + pivot^exp)으로 점수를 계산해요. value는 필드 값, exp는 지수 스케일링 계수, pivot은 value가 pivot보다 크면 점수가 0.5보다 크고 작으면 0.5보다 작아지도록 선택돼요. sigmoid 함수를 적용하려면 다음 Painless 메서드를 호출하세요:
double sigmoid(double
예제 (Example)
다음 예제 쿼리는 articles 인덱스에서 neural search 텍스트를 검색해요. 원래 문서 관련성 점수와 article_rank 값을 결합하며, 이 값은 먼저 sigmoid 함수로 변환돼요:
GET articles/_search
{
"query": {
"script_score": {
"query": {
"match": { "article_name": "neural search" }
},
"script" : {
"source" : "_score + sigmoid(doc['article_rank'].value, 11, 2)"
}
}
}
}
Random score (임의 점수) 함수
random score 함수는 [0, 1) 범위에서 균등하게 분포된 임의 점수를 생성해요. 함수가 어떻게 동작하는지 알아보려면 The random score function을 참고하세요. random score 함수를 적용하려면 다음 Painless 메서드 중 하나를 호출하세요:
double randomScore(int
예제 (Example)
다음 쿼리는 seed와 필드를 사용해 random_score 함수를 사용해요:
GET articles/_search
{
"query": {
"script_score": {
"query": {
"match": { "article_name": "neural search" }
},
"script" : {
"source" : "randomScore(20, '_seq_no')"
}
}
}
}
Decay 함수
decay 함수를 사용하면 근접성이나 최신성을 기준으로 결과에 점수를 매길 수 있어요. 자세한 내용은 Decay functions를 참고하세요. 지수(exponential), 가우시안(Gaussian), 선형(linear) 감쇠 곡선을 사용해 점수를 계산할 수 있어요. decay 함수를 적용하려면 필드 타입에 따라 다음 Painless 메서드 중 하나를 호출하세요:
Numeric fields: double decayNumericGauss(double
Geopoint fields: double decayGeoGauss(String
Date fields: double decayDateGauss(String
Example: Numeric fields
다음 쿼리는 숫자 필드에서 지수 decay 함수를 사용해요:
GET articles/_search
{
"query": {
"script_score": {
"query": {
"match": {
"article_name": "neural search"
}
},
"script": {
"source": "decayNumericExp(params.origin, params.scale, params.offset, params.decay, doc['article_rank'].value)",
"params": {
"origin": 50,
"scale": 20,
"offset": 30,
"decay": 0.5
}
}
}
}
}
Example: Geopoint fields
다음 쿼리는 지오포인트(geopoint) 필드에서 가우시안 decay 함수를 사용해요:
GET hotels/_search
{
"query": {
"script_score": {
"query": {
"match": {
"name": "hotel"
}
},
"script": {
"source": "decayGeoGauss(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
"params": {
"origin": "40.71,74.00",
"scale": "300ft",
"offset": "200ft",
"decay": 0.25
}
}
}
}
}
Example: Date fields
다음 쿼리는 날짜(date) 필드에서 선형 decay 함수를 사용해요:
GET blogs/_search
{
"query": {
"script_score": {
"query": {
"match": {
"name": "opensearch"
}
},
"script": {
"source": "decayDateLinear(params.origin, params.scale, params.offset, params.decay, doc['date_posted'].value)",
"params": {
"origin": "2022-04-24",
"scale": "6d",
"offset": "1d",
"decay": 0.25
}
}
}
}
}
Term frequency 함수
term frequency 함수는 점수 스크립트 소스에서 용어 수준 통계를 제공해요. 이 통계를 사용해 인기도에 따른 쿼리 시점의 곱셈/덧셈 점수 상향 같은 사용자 지정 정보 검색 및 순위 알고리즘을 구현할 수 있어요. term frequency 함수를 적용하려면 다음 Painless 메서드 중 하나를 호출하세요:
int termFreq(String
예제 (Example)
다음 쿼리는 fields 목록에 있는 각 필드의 총 용어 빈도(total term frequency)에 multiplier 값을 곱한 것으로 점수를 계산해요:
GET /demo_index_v1/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"script_score": {
"script": {
"source": """
for (int x = 0; x copy
Late interaction score (후기 상호작용 점수)
lateInteractionScore 함수는 토큰 수준 벡터 일치로 문서 관련성을 계산하는 Painless 스크립트 점수 함수예요. 각 쿼리 벡터를 모든 문서 벡터와 비교해 각 쿼리 벡터에 대한 최대 유사도를 찾고, 이 최대 점수들을 합산해 최종 문서 점수를 만들어요. Example score calculation: Query vectors: [[0.8, 0.1], [0.2, 0.9]] Document vectors: [[0.7, 0.2], [0.1, 0.8], [0.3, 0.4]] Query vector 1 → finds best match among document vectors → score A Query vector 2 → finds best match among document vectors → score B Final score = A + B 이 방식은 쿼리와 문서 사이의 세밀한 시맨틱 일치를 가능하게 해서, 검색 결과 재순위화(reranking)에 특히 효과적이에요.
인덱스 매핑 요구 사항
벡터 필드는 객체(object, 권장) 또는 float 타입으로 매핑되어야 해요. We recommend mapping the vector field as an object with "enabled": false because it stores raw vectors without parsing, improving performance:
{
"mappings": {
"properties": {
"my_vector": {
"type": "object",
"enabled": false
}
}
}
}
또는 벡터 필드를 float로 매핑할 수 있어요:
{
"mappings": {
"properties": {
"my_vector": {
"type": "float"
}
}
}
}
예제 (Example)
다음 예제는 방향에 기반해 벡터 유사도를 측정하는 코사인 유사도(cosine similarity)와 함께 lateInteractionScore 함수를 사용하는 방법을 보여줘요:
GET my_index/_search
{
"query": {
"script_score": {
"query": { "match_all": {} },
"script": {
"source": "lateInteractionScore(params.query_vectors, 'my_vector', params._source, params.space_type)",
"params": {
"query_vectors": [[1.0, 0.0], [0.0, 1.0]],
"space_type": "cosinesimil"
}
}
}
}
}
파라미터 (Parameters)
lateInteractionFunction은 다음 파라미터를 지원해요.
Parameter Data type Required Description
query_vectors | 배열의 배열(Array of arrays) | 필수 | 유사도 일치를 위한 쿼리 벡터예요.
vector_field | 문자열(String) | 필수 | 벡터가 들어 있는 문서 필드의 이름이에요.
doc | 맵(Map) | 필수 | 문서 소스예요 (params._source 사용).
space_type String No Similarity metric. Default: "l2"
space_type 파라미터는 유사도가 어떻게 계산되는지 결정하며 다음 유효한 값을 허용해요.
Space type Description Higher score means
innerproduct | 내적(dot product) | 더 유사한 벡터
cosinesimil | 코사인 유사도 | 더 유사한 방향
l2 (기본값) | 유클리드 거리 | 더 가까운 벡터 (반전)
전체 예제는 Reranking by a field using an externally hosted late interaction model을 참고하세요. search.allow_expensive_queries가 false로 설정되어 있으면 script_score 쿼리는 실행되지 않아요.
Customizing score calculation with built-in functionsSaturation