일반 sort에서 _script 로는 성능이 너무 나오지 않아서 다른 방법을 강구해보다가 같은 팀원분이 score로도 sort가 가능하니 그걸로 해보자는 의견을 주셔서 바로 실행해봤다.
두가지 방법이 있었다.
1.function_score 안에 script_sort 사용
QUERY문
{
"script_fields": {
"field1": {
"script": {
"lang": "painless",
"source": "params['_source']['field2'].findAll(t -> t.nested == 'test')"
}
}
},
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"terms": {
"_index": [
"index"
]
}
}
],
"filter": {
"bool": {
"must": [
{
"term": {
"fieldA": false
}
},
{
"term": {
"fieldB": true
}
}
]
}
}
}
},
"script_score": {
"script": {
"params": {"a": 1, "b": 2, "c": 3},
"source": "doc['fieldC'].value * params.a + doc['fieldD'].value * params.b + doc['fieldF'].value * params.c"
}
}
}
},
"_source": [
"field1",
"field2"
],
"sort": {
"_score": {
"order": "desc"
}
},
"size": 100,
"from": 0
}
→ query
아래 부분에 function_score
와 script_score
, 그리고 sort
부분 주목!
2. function_score 안에 field_value_factor 사용
QUERY문
{
"script_fields": {
"field1": {
"script": {
"lang": "painless",
"source": "params['_source']['field2'].findAll(t -> t.nested == 'test')"
}
}
},
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"terms": {
"_index": [
"index"
]
}
}
],
"filter": {
"bool": {
"must": [
{
"term": {
"fieldA": false
}
},
{
"term": {
"fieldB": true
}
}
]
}
}
}
},
"functions": [
{
"field_value_factor": {
"field": "fieldC",
"factor": 1,
"missing": 0
}
},
{
"field_value_factor": {
"field": "fieldD",
"factor": 2,
"missing": 0
}
},
{
"field_value_factor": {
"field": "fieldF",
"factor": 3,
"missing": 0
}
}
],
"score_mode": "sum",
"boost_mode" : "replace"
}
},
"_source": [
"field1",
"field2"
],
"sort": {
"_score": {
"order": "desc"
}
},
"size": 100,
"from": 0
}
→ query
아래 부분에 function_score
와 functions
, 그리고 sort
부분 주목!
functions
는 사용방법이 신기했다. 각 field_value_factor
를 토대로 하여 score가 계산된다. factor은 가중치라고 볼 수 있고, score_mode 는 각 field_value_factor
에 대한 처리를 의미한다. 또한, boost_mode 는 쿼리 결과의 스코어와 결합을 어떻게 할지에 대한 처리를 의미한다.
둘다 esrally 로 돌려봤는데, 2번 방법의 처리량이 훨씬 좋았다. 처리량차이가 200배정도 났다.