elasticsearch-model의 import 메소드의 transform 파라미터는 상당히 사용할 수 있는 아이

8222 단어 Elasticsearch
직장에서 검색 기능의 개선을 했을 때의 메모를, 은닉 사항을 포함하지 않는 부분만 공개해 이럴까라고 생각한다.

Hoge.__elasticsearch__.import 정의



포인트로서는

elasticsearch-model/lib/elasticsearch/model/importing.rb
          __find_in_batches(options) do |batch|
            response = client.bulk \
                         index:   target_index,
                         type:    target_type,
                         body:    __batch_to_bulk(batch, transform)

            yield response if block_given?

            errors +=  response['items'].select { |k, v| k.values.first['error'] }
          end

내부에서 find_in_batch를 사용하여 1000건씩, Elastcsearch의 대량 API를 사용해 데이터를 일괄 투입하는 스그레모노.
(여담이지만 find_in_batches의 디폴트가 1000인 것은 Elasticsearch-model이 아니라 ActiveRecord측의 정의. htps : // 기주 b. 코 m / 라이 ls / 라이 ls / b ぉ b / 6-0-s t ぇ / 아 c ゔ ぇ 레코 rd / ぃ b / 아 c ゔ ぇ _ 레코 rd / 레 치 온 / 바 tぇs. rb # L126 )

bulk insert뿐만 아니라 update, delete도 할 수 있다



Elasticsearch의 대량 API는 예를 들어
[
  { delete: { id: 123} },
  { index: { id: 124, data: { title: elasticsearch-modelが便利, ......... } } },
  { delete: { id: 125 } }
]

와 같은 페이로드를 지정하면,
  • 123, 125는 인덱싱되면 삭제합니다 (delete if exists)
  • 124는 아직 인덱싱되지 않은 경우 인덱싱 (insert or update)

  • 라고 하는 복잡한 일도 할 수 있다.

    앞에서 작성한 import 메소드 중, bulk API에 건네받고 있는 페이로드는 body: __batch_to_bulk(batch, transform) 로 그 정의를 더 보면(자)

    __batch_to_bulk
            def __batch_to_bulk(batch, transform)
              batch.map { |model| transform.call(model) }
            end
    

    transform이라고 하는 것을 model에 적용한 것의 리스트가 건네지는 것 같다.

    이 변환은 기본값입니다.
    https://魏Tub. 작은 m / 에스 땅 c / 에아스 땅 c 세아 rch 라일 ls / b ぉ b / V6. / 조류에서 l / 야스다 p 손 rs / 아 c 지 베 _ 레코 rd. rb#L114
    에 정의가 있듯이

    __transform
              def __transform
                lambda { |model|  { index: { _id: model.id, data: model.__elasticsearch__.as_indexed_json } } }
              end
    

    모델을 그대로 insert or update 하는 변환이 되어 있다.

    예를 들어, 초안과 공개 후에 모델을 나누지 않은 것 같은 Article 같은 모델이 있으면, 이 변환은 상당히 사용할 수 있어,

    게시됨과 초안을 분리하여 가져오기
    # 公開済みの記事はインデックスする
    Article.__elasticsearch__.import(scope: :published)
    
    # 下書き状態のもの、公開後に下書きに戻されたものは、インデックスがある場合には削除する
    Article.__elasticsearch__.import(
      scope: :draft,
      transform: ->(model) {
        { delete: { _id: model.id } }
      }
    )
    

    와 같이 transform 지정하는 것으로, 공개가 끝난 것만을 선택적으로 Elasticsearch측에 동기할 수 있다.

    또는 (가독성과의 균형에 따라)

    공개 완료와 초안을 나누어 import한다②
    
    Article.__elasticsearch__.import(
      transform: lambda do |article|
        if article.published?
          { index: { _id: article.id, data: article.__elasticsearch__.as_indexed_json } }
        else
          { delete: { _id: article.id } }
        end
      end
    )
    

    이렇게 하면 bulk API를 두드리는 횟수 자체를 줄일 수 있을 것 같다.

     

    원래, 웹서비스(Rails)+스마트폰 앱을 만들 때 하지 말아야 할 것 2018년판 그래도 썼는데, 모델 나누자! 라고 이야기 하지만 ... 역사적인 경위와 모모로 그렇게는 가지 않을 때에는, transform 파라미터는 꽤 사용할 수 있는 아이라고 생각한다.

    좋은 웹페이지 즐겨찾기