我在Rails应用程序中使用elasticsearch。我希望我的搜索结果可以按价格排序,因此我将price属性添加到映射中。在此之前,我能够成功搜索我指定的其他字段。现在我收到这样的错误:
Elasticsearch :: Transport :: Transport :: Errors :: BadRequest in Search#search: [400] {“error”:“SearchPhaseExecutionException [Failed] 执行阶段[查询],所有分片都失败了; shardFailures {[7aIAvW_pSlCg7HDBXwNvXA] [产品] [0]: SearchParseException [[products] [0]:from [-1],size [-1]:Parse Failure [无法解析源代码 [{\ “查询\”:{\ “布尔\”:{\ “应当\”:[{\ “multi_match \”:{\ “查询\”:\ “电子\”,\ “模糊\”:2 ,\ “字段\”:[\ “名称^ 2 \”,\ “描述\”,\ “category.name \”,\ “价格\”],\ “的prefix_length \”:2,\ “操作符\” :\“和\”}}]}}}]]]; 嵌套:NumberFormatException [输入字符串:\“electronics \”]; }
如果我从映射中删除price属性,我会获得搜索结果,但订单不正确。似乎结果按第一个数字排序,像我想的那样对待,例如1111似乎小于200,因为第一个数字'1'小于'2'。
有什么想法吗?
搜索控制器:
class SearchController < ApplicationController
def search
options = { sort: params[:s] }
@products = Product.search(params[:q], options).paginate(page: params[:page], per_page: 5).records
end
end
产品型号:
require "elasticsearch/model"
class Product < ActiveRecord::Base
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
def self.search(query, options={})
@search_definition = {
query: {} }
unless query.blank?
@search_definition[:query] = {
bool: {
should: [
{ multi_match: {
query: query,
fuzziness: 2,
fields: ['name^2', 'description','category.name', 'price'],
prefix_length: 2,
operator: 'and'}}]}}
else
@search_definition[:query] = { match_all: {} }
@search_definition[:sort] = [{ created_at: { order: "desc" }}]
end
if options[:sort] == 'Newest'
@search_definition[:sort] = [{ created_at: { order: "desc" }}]
@search_definition[:track_scores] = true
elsif options[:sort] == 'Price - Descending'
@search_definition[:sort] = [{ price: { order: "desc" }}]
@search_definition[:track_scores] = true
elsif options[:sort] == 'Price - Ascending'
@search_definition[:sort] = [{ price: { order: "asc" }}]
@search_definition[:track_scores] = true
end
__elasticsearch__.search @search_definition
end
settings analysis: {
analyzer: {
my_index_analyzer: {
type: "custom",
tokenizer: "standard",
filter: ["standard", "lowercase", "translation"] },
my_search_analyzer: {
type: "custom",
tokenizer: "standard",
filter: ["standard", "lowercase"] }
},
filter: {
translation: {
type: "nGram",
min_gram: 2,
max_gram: 20 }}
}
mapping do
indexes :name, type: 'string', index_analyzer: 'my_index_analyzer', search_analyzer: 'my_search_analyzer'
indexes :description, type: 'string', index_analyzer: 'my_index_analyzer', search_analyzer: 'my_search_analyzer'
indexes :created_at, type: 'date'
indexes :price, type: 'double', index: "not_analyzed"
indexes :category do
indexes :name, type: 'string', index_analyzer: 'my_index_analyzer', search_analyzer: 'my_search_analyzer'
end
end
def as_indexed_json(options={})
as_json(
only: [:name, :description, :price, :created_at],
include: { category: { only: :name } }
)
end
search.html.erb:
<div class="container main-body">
<h2>Search results</h2>
<div class="clearfix">
<ul class="list-inline pull-right">
<li><h5>Show search results by:</h5></li>
<li>
<div class="btn-group">
<button class="btn btn-default btn-md dropdown-toggle" type="button" data-toggle="dropdown">
<% sort = case
when params[:s] then params[:s]
when params[:q].blank? then 'Newest'
else 'Relevancy'
end
%>
<%= sort.humanize %> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><%= link_to "Relevancy", search_path(params.except(:controller, :action).merge(s: nil)), class: 'btn-xs' %></li>
<li><%= link_to "Newest", search_path(params.except(:controller, :action).merge(s: 'Newest')), class: 'btn-xs' %></li>
<li><%= link_to "Price - Descending", search_path(params.except(:controller, :action).merge(s: 'Price - Descending')), class: 'btn-xs' %></li>
<li><%= link_to "Price - Ascending", search_path(params.except(:controller, :action).merge(s: 'Price - Ascending')), class: 'btn-xs' %></li>
</ul>
</div></li>
</ul>
</div>
<div class="clearfix">
<%= render partial: 'products/products_form' %>
</div>
<div class="centered"><%= will_paginate @products %></div>
</div>
答案 0 :(得分:1)
问题和解决方案列在https://github.com/elastic/elasticsearch/issues/3975
问题是multi_match查询。它只适用于字符串。
编辑:
@search_definition[:query] = {
bool: {
should: [
{ multi_match: {
query: query,
fuzziness: 2,
fields: ['name^2', 'description','category.name', 'price'],
lenient: true
prefix_length: 2,
operator: 'and'}}]}}