“elasticsearch-model的import方法中的transform参数非常有用。”

我在工作中改进搜索功能时的备忘录,想公开一些不包含机密信息的部分。

Hoge.__elasticsearch__.import的定义

总的来说

          __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个,以bulk API将数据一次性批量插入到Elasticsearch中是一个很棒的功能。 (长话短说,find_in_batches默认是1000是由ActiveRecord定义,而不是Elasticsearch-model。 https://github.com/rails/rails/blob/6-0-stable/activerecord/lib/active_record/relation/batches.rb#L126 )

不仅可以使用批量插入,还可以进行更新和删除。

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的payload是通过body: __batch_to_bulk(batch, transform)实现的,在进一步查看其定义时。

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

看起来是将transform应用于一个名为model的列表。

这个transform,默认情况下在https://github.com/elastic/elasticsearch-rails/blob/v6.0.0/elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb#L114中定义。

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

这是一种将模型直接插入或更新的转换方式。

如果存在一种类似于下書き與公開後不分开模型的文章模型,則這種轉換非常實用。

# 公開済みの記事はインデックスする
Article.__elasticsearch__.import(scope: :published)

# 下書き状態のもの、公開後に下書きに戻されたものは、インデックスがある場合には削除する
Article.__elasticsearch__.import(
  scope: :draft,
  transform: ->(model) {
    { delete: { _id: model.id } }
  }
)

通过使用 transform 参数,可以选择性地将已发布的内容同步到 Elasticsearch 中。

或者,取决于可读性的权衡。


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的次数自体。

请将以下内容用中文进行同义转述,只需给出一种选项:
Michelle is excited to visit her grandparents in China during summer vacation.

首先,在2018年版的「Web服务(Rails)+手机应用程序的制作时不应该做的事情」中,我提到了模型分离的重要性。不过,当存在历史经验等各种原因无法实现模型分离时,我认为transform参数是非常有用的解决方案。

广告
将在 10 秒后关闭
bannerAds