Jor*_*kin 3 ruby search elasticsearch tire
我正在使用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, type: 'string', 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
Run Code Online (Sandbox Code Playgroud)
正如你可以在上面看到,我正在做一些数据的前/后处理/从elasticsearch为了得到什么,我从"product_traits"字段希望.这是感觉不对的问题,也是我的问题所在.
我有大量的产品目录,每个产品都有一些"特征",如颜色,材料和品牌.由于这些特征是如此多样化,我将数据建模为包含一个Trait模型,该模型通过ProductTrait模型与Product模型相关,该模型保存给定产品的特征值.
第一个问题是:如何创建弹性搜索映射以正确索引这些特征?我假设这涉及嵌套类型,但我无法充分理解文档来解决它.
第二个问题:我希望facets以组的形式返回(以我在上述search方法结束时处理它们的方式),但是计数反映了有多少匹配而没有考虑每个特征的当前选择值.例如:如果用户搜索"Glitter"然后单击与"蓝色"构面对应的链接,我希望所有"颜色"构面保持可见并显示对应查询结果的计数
而不使用"蓝色"过滤器.我希望这是一个很好的解释,对不起,如果它需要更多的澄清.
DrT*_*ech 21
如果您将特征索引为:
[
{
trait: 'color',
value: 'green'
},
{
trait: 'material',
value: 'plastic'
}
]
Run Code Online (Sandbox Code Playgroud)
这将在内部编入索引:
{
trait: ['color', 'material' ],
value: ['green', 'plastic' ]
}
Run Code Online (Sandbox Code Playgroud)
这意味着你可以永远只能查询其中有一个文档trait与价值"色"和value与价值green.这trait和之间没有任何关系value.
您有几个选择来解决此问题.
作为单一条款
你已经做的第一个,这是一个很好的解决方案,即将特征存储为单个术语,如:
['color#green`','material#plastic']
Run Code Online (Sandbox Code Playgroud)
作为对象
另一种方法(假设您的特征名称数量有限)将它们存储为:
{
traits: {
color: 'green',
material: 'plastic'
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以对traits.color或运行查询traits.material.
作为嵌套
如果要保留数组结构,则可以使用嵌套类型,例如:
{
"mappings" : {
"product" : {
"properties" : {
... other fields ...
"traits" : {
"type" : "nested",
"properties" : {
"trait" : {
"index" : "not_analyzed",
"type" : "string"
},
"value" : {
"index" : "not_analyzed",
"type" : "string"
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
每个特征/值对将在内部编入索引作为单独的(但相关的)文档,这意味着特征与其值之间将存在关系.您需要使用嵌套查询或嵌套过滤器来查询它们,例如:
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"
}
}
]
}
}
}
}
}
}
'
Run Code Online (Sandbox Code Playgroud)
结合facet,过滤和嵌套文档
您声明,当用户过滤时,例如color == green您只想显示结果color == green,但您仍想显示所有颜色的计数.
为此,您需要将filterparam用于搜索API而不是筛选查询.过滤后的查询会在计算构面之前过滤掉结果.在filter计算facet之后,param将应用于查询结果.
下面是一个示例,其中最终查询结果仅限于docs,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"
}
}
}
}
}
'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4235 次 |
| 最近记录: |