【问题标题】:ElasticSearch : Combining query string with term filtersElasticSearch:将查询字符串与术语过滤器相结合
【发布时间】:2013-06-22 19:24:31
【问题描述】:

我在我的 rails 项目中使用了轮胎和 elasticsearch,这是一个汽车零件零售网站。 ES 正在为用于浏览零件目录的多面搜索页面提供支持。我的问题是:如何使术语过滤器在使用查询字符串搜索相同字段时仅返回完全匹配,仅在查询字符串上使用分析器?

我希望这是有道理的。我将尝试提供一个示例:

有问题的模型/索引称为零件。假设某个部件具有称为categoriessub_categories 的映射。如果用户选择了 Brake category 和 Brake Caliper Carrier subcategory(创建术语过滤器),我必须确保 Brake Caliper subcategory 中的零件> 也不会返回 - 它是一个单独的子类别。但是,我确实希望用户能够在搜索字段中简单地输入“刹车”之类的内容(创建一个 query_string),并从所有这些类别中的产品中获取结果。

以下是 Part 模型的相关代码:

def to_indexed_json
    fits = fitments.try(:map) do |fit|
      {
        make: fit.try(:make).try(:name),
        make_id: fit.try(:make).try(:id),
        model: fit.try(:model).try(:name),
        model_id: fit.try(:model).try(:id),
        year: fit.year,
        sub_model: fit.sub_model
      }
    end
    {
      id: id,
      name: name,
      description: description,
      fitments: fits,
      categories: root_categories,
      sub_categories: sub_categories,
      price: price,
      condition_id: condition_id,
      country_of_origin: country_of_origin,
      brand: brand,
      oem: oem,
      thumb_url: part_images.first.try(:image).try(:thumb).try(:url),
      city: user.try(:city),
      inventory: inventory,
      part_number: part_number,
      user: user.try(:public_name)
    }.to_json
  end

  mapping do
    indexes :id, type: 'integer'
    indexes :name, analyzer: 'snowball', boost: 40
    indexes :description, analyzer: 'snowball', boost: 12

    indexes :price, type: "integer"
    indexes :country_of_origin, index: :not_analyzed
    indexes :condition_id, type: "integer"
    indexes :brand, index: :not_analyzed
    indexes :oem, type: "boolean"
    indexes :city, index: :not_analyzed
    indexes :inventory, type: "integer"
    indexes :part_number, index: :not_analyzed
    indexes :user, index: :not_analyzed

    indexes :thumb_url, index: :not_analyzed

    indexes :fitments do
      indexes :make
      indexes :make_id, type: "integer" #, index: 'not_analyzed'
      indexes :model
      indexes :model_id, type: "integer" #, index: 'not_analyzed'
      indexes :year, type: "integer"
      indexes :sub_model
    end

    indexes :categories do
      indexes :name, index: :not_analyzed
      indexes :id, type: "integer"
    end

    indexes :sub_categories do
      indexes :name, index: :not_analyzed
      indexes :id, type: "integer"
    end

  end

def search(params={})

  query_filters = []

  tire.search(:page => params[:page], :per_page => 20) do

    query_filters << { :term => { 'fitments.make_id' => params[:make] }} if params[:make].present?
    query_filters << { :term => { 'fitments.model_id' => params[:model] }} if params[:model].present?
    query_filters << { :term => { 'categories.name' => params[:category] }} if params[:category].present?
    query_filters << { :term => { 'sub_categories.name' => params[:sub_category] }} if params[:sub_category].present?
    query_filters << { :term => { 'city' => params[:city] }} if params[:city].present?
    query_filters << { :term => { 'condition_id' => params[:condition] }} if params[:condition].present?
    query_filters << { :term => { 'brand' => params[:brand] }} if params[:brand].present?
    query_filters << { :term => { 'oem' => params[:oem] }} if params[:oem].present?

    query do
      filtered do
        query {
          if params[:query].present?
            string params[:query]
          else
            all
          end
        }
        filter :and, query_filters unless query_filters.empty?
      end
    end

    facet("categories") { terms 'categories.name', size: 50 } unless params[:category].present?
    facet("cities") { terms 'city', size: 50 } unless params[:city].present?
    if params[:category].present? && !params[:sub_category].present?
      facet("sub_categories") { terms 'sub_categories.name', size: 50 }
    end
    facet("condition_id") { terms 'condition_id', size: 50 } unless params[:condition].present?
    facet("brand") { terms 'brand', size: 50 } unless params[:brand].present?
    facet("oem") { terms 'oem', size: 2 } unless params[:oem].present?

    size params[:size] if params[:size]

  end
end

【问题讨论】:

    标签: ruby-on-rails elasticsearch tire


    【解决方案1】:

    您必须使用 Elasticsearch 的multi_field 功能并过滤未分析的字段;见例如。 Why multi-field mapping is not working with tire gem for elasticsearch?

    【讨论】:

    • 谢谢卡米。您在这里支持您的宝石,这是一个巨大的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2016-06-09
    • 2012-11-09
    • 2011-07-25
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多