【问题标题】:ElasticSearch add mapping to a numeric, gives me errorElasticSearch 将映射添加到数字,给我错误
【发布时间】:2015-12-26 15:56:08
【问题描述】:

我在 Rails 应用程序中使用弹性搜索。我希望我的搜索结果可以按价格排序,所以我将价格属性添加到映射中。在此之前,我能够成功搜索我指定的其他字段。现在我收到这样的错误:

Elasticsearch::Transport::Transport::Errors::BadRequest in Search#search: [400] {"error":"SearchPhaseExecutionException[Failed 执行阶段[查询],所有分片失败;分片失败 {[7aIAvW_pSlCg7HDBXwNvXA][产品][0]: SearchParseException[[products][0]: from[-1],size[-1]: 解析失败 [解析源失败 [{\"query\":{\"bool\":{\"should\":[{\"multi_match\":{\"query\":\"electronics\",\"fuzziness\":2 ,\"fields\":[\"name^2\",\"description\",\"category.name\",\"price\"],\"prefix_length\":2,\"operator\" :\“和\”}}]}}}]]]; 嵌套:NumberFormatException[对于输入字符串:\"electronics\"]; }

如果我从映射中删除价格属性,我会得到搜索结果,但顺序不正确。似乎结果是按第一个数字排序的,像我认为的字符串一样对待,例如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>

【问题讨论】:

    标签: ruby-on-rails elasticsearch


    【解决方案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'}}]}}
    

    【讨论】:

    • 我不知道。你能建议如何修改我的查询,因为我不熟悉弹性搜索。无论如何,谢谢你的回答。
    • 我也是这个领域的新手。但我认为如果您使用的是 muti_match 查询,这将起作用。检查我的编辑。
    • 我只是将lenient: true 添加到我的查询中,现在看起来还可以。再次感谢。
    猜你喜欢
    • 2015-08-10
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多