업무에서 OpenSearch를 활용해서 검색을 할 때, 두 가지 문제가 있었습니다.
첫째, total_count가 일정하지 않음.
OpenSearch에서 검색할 때, total_count는 res["hits"]["total"]["value"]로 가져올 수 있습니다.
하지만, 이는 query 안에 있는 조건에 해당하는 경우만, 일정한 count 값을 돌려줍니다.
query 바깥에서 search_after_count를 통해 pagination을 하기 때문에 이 값이 페이지를 넘어갈 때마다 달라질 수 밖에 없었습니다.
둘째, 페이지를 넘기는 중에도 새로운 데이터가 계속 추가됨.
페이지를 넘기는 중에도, 새로운 데이터가 계속 추가되어서 일관된 정보를 보여줄 수가 없습니다.
total_count를 cache에 넣어서 해결
첫번째 페이지를 검색할 때의 total_count가 전체 total_count이므로 이를 cache에 보관하고 다음 페이지를 검색할 때 꺼내썼습니다.
PIT(Point in Time) 기능을 이용해 일정 시점의 데이터를 얼려둘 수 있습니다. PIT를 create하고 id 값을 cache를 이용해 공유하면서 문제를 해결했습니다.
docs : https://opensearch.org/docs/2.4/opensearch/point-in-time#paginating-search-results
opensearchpy 를 활용하였습니다.
PIT 생성
먼저 PIT를 생성합니다.
pit = ops.create_point_in_time(index=opensearch_indexes, keep_alive="1m")
index에는 필요한 인덱스들을 넣어주면 되고, keep_alive는 PIT가 유지되는 시간입니다.
# Response
{
"pit_id": "4_r-QAMPdG1zX2xvZ18yMDIzLTA5FmFYUmJ4R3B4UTY2RGIxZ2xZaFpPTWcAFmhXSi1BMVl5U2hLREJ0N1o5anZZYWcAAAAAAADS1kYWWEpFbWxvd0lTWWUzV0pFVDRIbUVBURJ0bXNfZGJfbG9nXzIwMjMtMDgWUTRTc3llT2dTb0tFb3lEUk4yMzh1UQAWaFdKLUExWXlTaEtEQnQ3WjlqdllhZwAAAAAAANLWRRZYSkVtbG93SVNZZTNXSkVUNEhtRUFRD3Rtc19sb2dfMjAyMy0xMBZjY3o3ZzljY1RlQ2I3VHZFZEdoUHVBABZoV0otQTFZeVNoS0RCdDdaOWp2WWFnAAAAAAAA0tZHFlhKRW1sb3dJU1llM1dKRVQ0SG1FQVEDFmFYUmJ4R3B4UTY2RGIxZ2xZaFpPTWcAABZjY3o3ZzljY1RlQ2I3VHZFZEdoUHVBAAAWUTRTc3llT2dTb0tFb3lEUk4yMzh1UQAA",
"_shards": {"total": 3, "successful": 3, "skipped": 0, "failed": 0},
"creation_time": 1696927693903,
}
여기서, pit_id를 잘 가지고 있다가, 추후 검색 시에 활용하면 됩니다.
이 때 주의할 점은 pit_id는 대상이 되는 index가 이미 정해져 있기 때문에,
pit_id를 이용해 검색 시에는 index를 지정해주면 안됩니다!
PIT 갱신
PIT의 keep_alive는 1분(60000ms)로 정해져있는데, 반복해서 검색할 때, 이 시간을 갱신해줄 수 있습니다.
body["pit"] = {
"id": pit_key,
"keep_alive": "1m",
}
검색할 body에 pit_key를 넣어주고, keep_alive 시간을 갱신해주면 됩니다.
💡 첫 페이지에서 PIT를 생성하고, 이후엔 cache를 통해 갱신하는 방식으로 사용하려고 합니다.