from, size로 페이징은 기본값이 10,000이다.
그 이후로 "from":"10100" 이렇게 사용하려면 max_result_window 을 올려야한다.
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/searchopen context의 개수를 확인할 수 있다.
사용하지 않는 open context의 개수를 지울 수 있다.DELETE /_search/scroll { "scroll_id" : [ "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==", "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAABFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAAAxZrUllkUVlCa1NqNmRMaUhiQlZkMWFBAAAAAAAAAAIWa1JZZFFZQmtTajZkTGlIYkJWZDFhQQAAAAAAAAAFFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAABBZrUllkUVlCa1NqNmRMaUhiQlZkMWFB" ] }
살아있는 모든 context를 닫을 경우
DELETE /_search/scroll/_allscroll_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"
},
"TT": {
"order": "desc"
}
}
]
}
search_after 사용시 반드시 unique값 하나는 포함하여 정렬해주어야 한다.(ID)
{
"_index" : "test_k",
"_type" : "_doc",
"_id" : "123123",
"_score" : null,
"_source" : {
"ID" : "123123",
"NAME" : "(주)에너지",
"TT" : "GREEN"
},
"sort" : [
"123123",
"green"
]
}
GET test_k/_search
{
"query": {
"match_all": {
}
},
"sort": [
{
"ID": {
"order": "desc"
},
"TT": {
"order": "desc"
}
}
], "search_after": [ // 해당값은 unique한 값이야 함.
"123123", // 여기서 ID 필드가 unique.
"green"
]
}
search_after 에 첫 검색결과의 마지막 sort값을 넣으면 그 후의 문서를 반환한다.
- search_after에 넣은 sort정보가 49번째 doc의 sort값이다.
그래서 위의 쿼리로 50~59번의 doc을 받을 수 있다.- unique값 하나만 있으면 필드값이 2개이상이여도 페이징 되는것 같다.
[참고] https://stackoverflow.com/questions/68127892/how-does-search-after-work-in-elastic-search
주의점)
페이징 시점 sort되는 값이 변동되면 이전 결과를 보장 받을 수 없다.
(색인 중에 페이징시 문제 발생 가능성)
문제)
from 값을 사용할 수 없기 때문에, UI에서 더보기 버튼이나 스크롤 방식이 아닌 페이지 번호 조회인 경우는 사용할 수 없습니다.
ex. 결과 200 페이지에서 100개 보기 이런 기능 불가능!
point in time 이라는 기능도 확인해보면 좋겠다.