加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 如何使用ElasticSearch映射/查询此数据?

发布时间:2020-12-17 01:53:49 所属栏目:百科 来源:网络整理
导读:我正在使用ElasticSearch和轮胎宝石来为搜索提供动力 我的网站的功能.我无法弄清楚如何映射和 查询数据以获得我需要的结果. 相关代码如下.我将在下面解释所需的内容 好. # models/product.rbclass Product ActiveRecord::Base include Tire::Model::Search i
我正在使用ElasticSearch和轮胎宝石来为搜索提供动力
我的网站的功能.我无法弄清楚如何映射和
查询数据以获得我需要的结果.

相关代码如下.我将在下面解释所需的内容
好.

# models/product.rb

class Product < ActiveRecord::Base
  include Tire::Model::Search
  include Tire::Model::Callbacks

  has_many :categorizations
  has_many :categories,:through => :categorizations
  has_many :product_traits
  has_many :traits,:through => :product_traits

  mapping do
    indexes :id,type: 'integer'
    indexes :name,boost: 10
    indexes :description,analyzer: 'snowball'
    indexes :categories do
      indexes :id,type: 'integer'
      indexes :name,type: 'string',index: 'not_analyzed'
    end
    indexes :product_traits,index: 'not_analyzed'
  end

  def self.search(params={})

    out = tire.search(page: params[:page],per_page: 12,load: true) do
      query do
        boolean do

          must { string params[:query],default_operator: "OR" } if params[:query].present?
          must { term 'categories.id',params[:category_id] } if params[:category_id].present?

          # if we aren't browsing a category,search results are "drill-down"
          unless params[:category_id].present?
            must { term 'categories.name',params[:categories] } if params[:categories].present?
          end
          params.select { |p| p[0,2] == 't_' }.each do |name,value|
            must { term :product_traits,"#{name[2..-1]}##{value}" }
          end

        end
      end

      # don't show the category facets if we are browsing a category
      facet("categories") { terms 'categories.name',size: 20 } unless params[:category_id].present?
      facet("traits") {
        terms :product_traits,size: 1000 #,all_terms: true
      }

      # raise to_curl
    end

    # process the trait facet results into a hash of arrays
    if out.facets['traits']
      facets = {}
      out.facets['traits']['terms'].each do |f|
        split = f['term'].partition('#')
        facets[split[0]] ||= []
        facets[split[0]] << { 'term' => split[2],'count' => f['count'] }
      end
      out.facets['traits']['terms'] = facets
    end

    out
  end

  def to_indexed_json
    {
      id: id,name: name,description: description,categories: categories.all(:select => 'categories.id,categories.name,categories.keywords'),product_traits: product_traits.includes(:trait).collect { |t| "#{t.trait.name}##{t.value}" }
    }.to_json
  end

end

如您所见,我正在对数据进行一些前/后处理
往返于弹性搜索,以获得我想要的东西
‘product_traits’字段.这是我感觉不对的地方
问题起源于.

我有大量的产品目录,每个产品都有一些“特征”
作为颜色,材料和品牌.由于这些特征是多种多样的,我
将数据建模为包括与产品相关的特性模型
通过ProductTrait模型建立模型,该模型保存特征的值
给定的产品.

第一个问题是:我如何创建弹性搜索映射到索引
这些特质适当吗?我假设这涉及嵌套类型,但我
无法充分理解文档来弄明白.

第二个问题:我希望各个方面能够成群结队地回归
我在搜索方法结束时处理它们的方式
以上)但计数反映了没有多少匹配
考虑每个特征的当前选定值.对于
示例:如果用户搜索“Glitter”,然后单击该链接
对应于’蓝色’方面,我想要所有’颜色’方面
保持可见并显示对应查询结果的计数
没有’蓝色’过滤器.我希望这是一个很好的解释,
对不起,如果需要更多说明.

解决方法

如果您将特征索引为:

[
    {
        trait: 'color',value: 'green'
    },{
        trait: 'material',value: 'plastic'
    }
]

这将在内部编入索引:

{
    trait: ['color','material' ],value: ['green','plastic' ]
}

这意味着您只能查询具有值’color’的特征和值为green的值的文档.特质与价值之间没有关系.

您有几个选择来解决此问题.

作为单一条款

你已经做的第一个,这是一个很好的解决方案,即将特征存储为单个术语,如:

['color#green`','material#plastic']

作为对象

另一种方法(假设您的特征名称数量有限)将它们存储为:

{
    traits: {
        color:    'green',material: 'plastic'
    }
}

然后你可以对traits.color或traits.material运行查询.

作为嵌套

如果要保留阵列结构,则可以使用nested type,例如:

{
   "mappings" : {
      "product" : {
         "properties" : {

            ... other fields ...

            "traits" : {
               "type" : "nested","properties" : {
                  "trait" : {
                     "index" : "not_analyzed","type" : "string"
                  },"value" : {
                     "index" : "not_analyzed","type" : "string"
                  }
               }
            }
         }
      }
   }
}

每个特征/值对将在内部编入索引作为单独的(但相关的)文档,这意味着特征与其值之间将存在关系.您需要使用nested queries或nested filters来查询它们,例如:

curl -XGET 'http://127.0.0.1:9200/test/product/_search?pretty=1'  -d '
{
   "query" : {
      "filtered" : {
         "query" : {
            "text" : {
               "name" : "my query terms"
            }
         },"filter" : {
            "nested" : {
               "path" : "traits","filter" : {
                  "and" : [
                     {
                        "term" : {
                           "trait" : "color"
                        }
                     },{
                        "term" : {
                           "value" : "green"
                        }
                     }
                  ]
               }
            }
         }
      }
   }
}
'

结合facet,过滤和嵌套文档

您声明,当用户过滤例如color == green时,您希望仅在color == green的位置显示结果,但您仍希望显示所有颜色的计数.

为此,您需要使用过滤器参数到search API,而不是过滤查询.过滤后的查询会在计算构面之前过滤掉结果.过滤器参数在计算小平面后应用于查询结果.

下面是一个示例,其中最终查询结果仅限于doc = color == green的文档,但会计算所有颜色的facet:

curl -XGET 'http://127.0.0.1:9200/test/product/_search?pretty=1'  -d '
{
   "query" : {
      "text" : {
         "name" : "my query terms"
      }
   },"filter" : {
      "nested" : {
         "path" : "traits","filter" : {
            "and" : [
               {
                  "term" : {
                     "trait" : "color"
                  }
               },{
                  "term" : {
                     "value" : "green"
                  }
               }
            ]
         }
      }
   },"facets" : {
      "color" : {
         "nested" : "traits","terms" : { "field" : "value" },"facet_filter" : {
            "term" : {
               "trait" : "color"
            }
         }
      }
   }
}
'

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读