from, size로 페이징은 기본값이 10,000이다.
그 이후로 "from":"10100" 이렇게 사용하려면 max_result_window 을 올려야한다.(페이징을 위해 대략 전체문헌수인 2억으로 잡혀있음)
elasticsearch가 from,size로 요청한 페이지가지 모든 문서를 메모리에 로드한 다음 정렬하고 요청 내용을 반환한다.
요청당 필요한 메모리는 from+size의 크기에 비례한다. 즉, 건너뛰는 결과가 많을 수록(1000~1010) 쿼리가 느려져 큰 결과 집합을 페이징하는데 소요 시간이 더 걸릴 수 있다.
max_result_window를 100으로 해뒀을때 그 이후 문헌도 페이징 결과로 나올 수 있는지 테스트
PUT test_k/_settings
{
"index": {
"max_result_window": "100"
}
}
1m은 elastic에게 search context를 1m 추가로 유지하라고 말하는것.
GET test_k/_search?scroll=1m
{
"query": {
"match_all": {
}
}
}
scroll에선 from 사용 불가. size 가능.
{
"_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFlVLOXBTTkNSUU1xNURLUUhkdVdHZ0EAAAAAACmN9BZjcWRLQ2Q4ZlNIR3MwbEdnbXJ6MDJB",
GET _search/scroll
{
"scroll":"1m",
"scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFlVLOXBTTkNSUU1xNURLUUhkdVdHZ0EAAAAAACmOJBZjcWRLQ2Q4ZlNIR3MwbEdnbXJ6MDJB"
}
{
"_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFlVLOXBTTkNSUU1xNURLUUhkdVdHZ0EAAAAAACmOJBZjcWRLQ2Q4ZlNIR3MwbEdnbXJ6MDJB",
다음결과를 이어 받기 위한 새로운 scroll_id가 생겼다.
GET _search/scroll
{
"scroll":"1m",
"scroll_id": ""FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFlVLOXBTTkNSUU1xNURLUUhkdVdHZ0EAAAAAACmOJBZjcWRLQ2Q4ZlNIR3MwbEdnbXJ6MDJB"
}
scroll은 문서를 다 읽은 후에도 search context가 지정한 시간만큼 살아있다.
GET /_nodes/stats/indices/search
open context의 개수를 확인할 수 있다.
사용하지 않는 open context의 개수를 지울 수 있다.DELETE /_search/scroll { "scroll_id" : [ "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==", "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAABFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAAAxZrUllkUVlCa1NqNmRMaUhiQlZkMWFBAAAAAAAAAAIWa1JZZFFZQmtTajZkTGlIYkJWZDFhQQAAAAAAAAAFFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAABBZrUllkUVlCa1NqNmRMaUhiQlZkMWFB" ] }
살아있는 모든 context를 닫을 경우
DELETE /_search/scroll/_all
scroll_id는 지정한 시간이 지나면 사라지는데. 그러면 scroll_id로 조회할때 error를 발생한다.
scroll_id를 1분동안 생성한다고 했을때 사용자가 2분 뒤 페이징 넘김을 실행하면 생성됬던 scroll_id는 없어져 error가 발생되고,
scroll_id 생성 시간을 오래 늘려두면 엔진이 담고 있는 search context가 너무 많아져 문제가 될것 같다.
시간초과의 문제 생각해봐야함.
라이브 커서를 제공하여 다음 페이지를 조회할 수 있다.
검색할때 sort 필드를 통해 정렬 조건을 부여하면 결과 값으로 sort필드를 반환하는데 다음 페이지를 검색하기 위해 search_after 필드 내 기존 결과 값 sort필드를 넣으주면
다음 페이지를 조회할 수 있다.
GET test_k/_search
{
"query": {
"match_all": {
}
},
"from":"40",
"sort": [
{
"SKEY": {
"order": "desc"
},
"TNEWS_KEY": {
"order": "desc"
}
}
]
}
search_after 사용시 반드시 unique값 하나는 포함하여 정렬해주어야 한다.(SKEY)
{
"_index" : "test_k",
"_type" : "_doc",
"_id" : "TKR7520160000011",
"_score" : null,
"_source" : {
"SKEY" : "TKR7520160000011",
"TNKWS" : "(주)수성에너지",
"TNEWS" : "GREEN"
},
"sort" : [
"tkr7520160000011",
"green"
]
}
GET test_k/_search
{
"query": {
"match_all": {
}
},
"sort": [
{
"SKEY": {
"order": "desc"
},
"TNEWS_KEY": {
"order": "desc"
}
}
],
첫 검색결과의 마지막 sort값을 넣으면 그 후의 문서를 반환한다.
"search_after": [ // 하는 반드시 unique한 값이야 함.
"tkr7520160000011",
"green"
]
}
search_after에 넣은 sort정보가 49번째 doc의 sort값이다.
그래서 위의 쿼리로 50~59번의 doc을 받을 수 있다.
[참고] https://stackoverflow.com/questions/68127892/how-does-search-after-work-in-elastic-search
GET kr/_search
{
"size": 5,
"query": {
"bool": {
"filter": [
{
"terms": {
"COLP": [
"1",
"2",
"3",
"4"
]
}
}
],
"must": [
{
"bool": {
"should": [
{
"match_phrase": {
"TI": "car"
}
},
{
"match_phrase": {
"TIW": "car"
}
}
]
}
}
]
}
},
"from": 0,
"_source": [
"SKEY",
"TIK"
],
"sort": [
{
"WRC": {
"order": "desc"
}
},
{
"XD.keyword": {
"order": "desc"
}
},
{
"SKEY": {
"order": "asc"
}
}
],
"search_after":[
10,
"20220503",
3522191000926
],
"aggs": {
"topn_skeys": {
"scripted_metric": {
"init_script": {
"id": "topn_skeys_init_script"
},
"map_script": {
"id": "topn_skeys_map_script"
},
"combine_script": {
"id": "topn_skeys_combine_script"
},
"params": {
"sort": [
{
"field": "WRC",
"order": "asc"
},
{
"field": "XD.keyword",
"order": "desc"
},
{
"field": "SKEY",
"order": "asc"
}
],
"topn": 20000
},
"reduce_script": {
"id": "topn_skeys_reduce_script"
}
}
},
"group_by_colp": {
"terms": {
"field": "COLP",
"size": 100
}
}
},
"track_total_hits": true
}
지금 wt에서 사용하는 쿼리로 결과에 sort
"sort" : [
10,
"20220502",
3522191000683
] 를
"search_after" : [
10,
"20220502",
3522191000683
]
이렇게 사용. unique값 하나만 있으면 필드값이 2개이상이여도 페이징 되는것 같다.
주의점)
sort되는 값이 변동되는 값이면 이전 결과를 보장 받을 수 없다. (색인 중에 페이징시 문제 발생 가능성)
문제)
from 값을 사용할 수 없기 때문에, UI에서 더보기 버튼이나 스크롤 방식이 아닌 페이지 번호 조회인 경우는 사용할 수 없습니다.
특정 시점의 색인에 대해
색인이 실시간으로 변경되지는 않기에 search after를 사용할때 pit를 함께 사용하지 않아도 될것 같다.