【问题标题】:Rails and Elasticsearch - Filters, weights, and statisticsRails 和 Elasticsearch - 过滤器、权重和统计信息
【发布时间】:2016-06-08 02:01:29
【问题描述】:

考虑以下模型

class MyModel # `Employee` used in concrete examples
  field :field1 # company_name used in concrete examples
  field :field2 # job_name used in concrete examples
  scope: filter1 # non_retired
  scope: filter2
end
  • 我需要过滤/执行命名搜索查询,例如按 non_retired 过滤
  • 我需要对某些字段进行加权(例如,将某些字段的重要性提高 3 倍)
  • 我需要根据 total 结果(即不仅仅是前 10 个分页结果)获取统计信息,例如,汇总 company_names(我的代码已经可以工作,但我遇到了问题获取“总”结果 ID。

我无法将所有这些放在一起。从Rails elasticsearch - named scope search 我了解到我需要将 id 直接提供给 Elasticsearch。

def search_by_id(query, type, ids, options = {})
  self.weighted_search(query, options.deep_merge({
    query: {
      multi_match: {
        filter: {
          ids: {
            values: ids
          }.tap do |filter|
          filter[:type] = type if type
        end
        }
      }
    }
  }))
end

def weighted_search(query, options = {})
  self.__elasticsearch__.search(
    {
      query: {
        multi_match: {
          query: query,
          fields: [
            "company_name^3",
            "job_name^2",
          ],
          # strategy: 'leap_frog_filter_first'
          # PROBLEM :cannot use this strategy on multi_match ?
        }
      }
    }.deep_merge(options)
  )
end

这会产生一个 BadRequest 错误,解释如下

[400] {"error":{"root_cause":[{"type":"query_parsing_exception","re​​ason":"[match] 查询不支持 [$oid]

我不明白这个错误...我无法按 id 过滤??

然后,假设我有这个工作,我如何提取与 ElasticSearch 匹配的 id 子集??

search = MyModel.search('query')
search.total_results # => 81
search.records.count # => 10

但我需要获取所有 81 个 ID,以便执行一些统计信息(即汇总公司名称,我已经有一些代码在工作,但现在我只汇总了前 10 个结果...)

【问题讨论】:

    标签: ruby-on-rails elasticsearch mongoid


    【解决方案1】:

    好的,这是我目前的解决方案(我不喜欢它,因为它对 DB 的影响很大)

    • 仅使用 MongoDB 命名范围来过滤记录,并提取它们的 id

      ids = @my_model_filtered.pluck(:id)
      
    • 将生成的 ID 发送到 ES,并在特定字段上进行评分搜索

      def search_by_id(query, type, ids, options = {})
        self.weighted_search(query, options.deep_merge({
          query: {
            filtered: {
              filter: {
                ids: {
                  values: ids.map(&:to_s)
                }.tap do |filter|
                filter[:type] = type if type
              end
              }
            }
          }
        }))
      end
      
      def weighted_search(query, options = {})
        self.__elasticsearch__.search(
          {
            query: {
              filtered: {
                query: {
                  multi_match: {
                    query: query,
                    fields: [
                      "company_name^3",
                      "job_name^2",
                      "xxx"
                    ],
                    type: "most_fields"
                  }
                }
              }
            }
       }.deep_merge(options)
        )
       end
      
    • 使用 Elasticsearch 提供的 ID 列表在 MongoDB 数据库上进行额外的信息提取(聚合等)

      @response = @searching.search_by_id(@query, @searchable_type, ids).per(10000) # setting a high per number so ES returns all IDs
      @all_records = @response.records.records
      
      # Further processing
      @all_records.map_reduce(...)
      

    【讨论】:

      猜你喜欢
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      相关资源
      最近更新 更多