OpenSearch Pagination - PIT(Point In Time)

leejm·2023년 10월 27일
0

업무에서 OpenSearch를 활용해서 검색을 할 때, 두 가지 문제가 있었습니다.

첫째, total_count가 일정하지 않음.

OpenSearch에서 검색할 때, total_count는 res["hits"]["total"]["value"]로 가져올 수 있습니다.

하지만, 이는 query 안에 있는 조건에 해당하는 경우만, 일정한 count 값을 돌려줍니다.

query 바깥에서 search_after_count를 통해 pagination을 하기 때문에 이 값이 페이지를 넘어갈 때마다 달라질 수 밖에 없었습니다.

둘째, 페이지를 넘기는 중에도 새로운 데이터가 계속 추가됨.

페이지를 넘기는 중에도, 새로운 데이터가 계속 추가되어서 일관된 정보를 보여줄 수가 없습니다.

해결

  1. total_count를 cache에 넣어서 해결

    첫번째 페이지를 검색할 때의 total_count가 전체 total_count이므로 이를 cache에 보관하고 다음 페이지를 검색할 때 꺼내썼습니다.

  2. PIT(Point in Time) 기능을 이용해 일정 시점의 데이터를 얼려둘 수 있습니다. PIT를 create하고 id 값을 cache를 이용해 공유하면서 문제를 해결했습니다.

PIT(Point in Time)

docs : https://opensearch.org/docs/2.4/opensearch/point-in-time#paginating-search-results

opensearchpy 를 활용하였습니다.

  1. 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를 지정해주면 안됩니다!

  2. PIT 갱신

    PIT의 keep_alive는 1분(60000ms)로 정해져있는데, 반복해서 검색할 때, 이 시간을 갱신해줄 수 있습니다.

    body["pit"] = {
                "id": pit_key,
                "keep_alive": "1m",
            }

    검색할 body에 pit_key를 넣어주고, keep_alive 시간을 갱신해주면 됩니다.

💡 첫 페이지에서 PIT를 생성하고, 이후엔 cache를 통해 갱신하는 방식으로 사용하려고 합니다.

profile
Python Based Backend Engineer입니다. DevOps와 효율적으로 일하는 것에 관심이 있습니다.

0개의 댓글