Tire Elastic中的自定义分析器不能与Mongoid一起使用

时间:2012-10-19 11:16:46

标签: ruby-on-rails mongoid elasticsearch tire

我还在做错事。 有人可以帮助我吗? 我想在Rails + Mongoid中创建一个带有ascii过滤器的自定义分析器。 我有一个简单的模型产品,它有字段名称。

class Product
  include Mongoid::Document

  field :name

  settings analysis: {
      analyser: {
        ascii: {
          type: 'custom',
          tokenizer: 'whitespace',
          filter: ['lowercase','asciifolding']
        }
      }
   }

   mapping do
     indexes :name, analyzer: 'ascii'
   end

end

Product.create(name:"svíčka")
Product.search(q:"svíčka").count #1
Product.search(q:"svicka").count #0 can't find - expected 1

Product.create(name:"svicka")
Product.search(q:"svíčka").count #0 can't find - expected 1
Product.search(q:"svicka").count #1

当我用elasticsearch-head检查索引时,我希望索引存储时没有像“svicka”这样的重音,但索引看起来像是“Svíčka”。

我做错了什么?

当我使用API​​检查它时看起来没问题:

curl -XGET 'localhost:9200/_analyze?tokenizer=whitespace&filters=asciifolding' -d 'svíčka'

{"tokens":[{"token":"svicka","start_offset":0,"end_offset":6,"type":"word","position":1}]}

http://localhost:9200/development_imango_products/_mapping
{"development_imango_products":{"product":{"properties":{"name":{"type":"string","analyzer":"ascii"}}}}}

curl -XGET 'localhost:9200/development_imango_products/_analyze?field=name' -d 'svíčka'
{"tokens":[{"token":"svicka","start_offset":0,"end_offset":6,"type":"word","position":1}]}

4 个答案:

答案 0 :(得分:1)

您可以使用analyze api检查实际索引文档的方式。

您还需要考虑到您的索引与存储内容之间存在差异。查询时会返回您存储的内容,而这正是您发送给elasticsearch的内容,而您索引的内容决定了查询时返回的文档。

对于usecase,使用asciifolding是一个不错的选择,它应该返回查询svíčka或svicka的结果。我想您的设置中只有一个拼写错误:analyser应为analyzer。可能没有像你期望的那样使用分析仪。

<强>更新
鉴于你的评论,你还没有解决问题。你能检查你的映射是什么样的(localhost:9200/index_name/_mapping)吗?您使用analyze api的方式并不是那么有用,因为您手动提供了文本分析链,但这并不意味着链是按照您对您的字段的预期应用的。如果你提供这样的字段名称会更好:

curl -XGET'localhost:9200 / index_name / _analyze?field = field_name'-d'svíčka'

这样,analyze api将依赖于该字段的实际映射。

更新2
在确保正确提交映射并且一切正常后,我注意到您没有指定要查询的字段。如果您未指定它,则查询_all特殊字段,该字段默认包含您要编制索引的所有字段,默认情况下使用StandardAnalyzer。您应该使用以下查询:name:svíčka

答案 1 :(得分:0)

elasticsearch需要在单个api调用中进行设置和映射。我不确定它是否在轮胎文档中提到,但我遇到了类似的问题,在设置轮胎时使用设置和映射。以下应该工作:

class Product
  include Mongoid::Document
  # include tire stuff

  field :name

  settings(self.tire_settings) do
    mapping do
      indexes :name, analyzer: 'ascii'
    end
  end

  # this method is just created for readablity, 
  # settings hash can also be passed directly
  def self.tire_settings
    {
      analysis: {
        analyzer: {
          ascii: {
            type: 'custom',
            tokenizer: 'whitespace',
            filter: ['lowercase','asciifolding']
          }
        }
      }
    }
  end
end

答案 2 :(得分:0)

  1. 您的设置/映射表示法不正确,正如@rubish建议的那样,检查https://github.com/karmi/tire/blob/master/lib/tire/model/indexing.rb中的文档(毫无疑问,文档应该更好)

  2. 始终,始终,始终检查索引的映射,以查看是否已应用所需的映射。

  3. 正如@javanna建议的那样,使用Explain API来检查分析链如何快速工作,而无需存储文档,检查结果等。

答案 3 :(得分:0)

请注意,在模型中添加两​​行以使其可通过Tire进行搜索非常重要。你的模型看起来应该是

  class Model
    include Mongoid::Document
    include Mongoid::Timestamps
    include Tire::Model::Search
    include Tire::Model::Callbacks

    field :filed_name, type: String

    index_name "#{Tire::Model::Search.index_prefix}model_name"
    settings :analysis => {
        :analyzer => {
            "project_lowercase_analyzer" => {
                "tokenizer" => "keyword",
                "filter"  =>  ["lowercase"],
                "type" => "custom"
                }
            },
        }  do
     mapping do
       indexes :field_name, :boost => 10, :type => 'String', :analyzer => 'standard', :filter => ['standard', 'lowercase','keyword']
       end
     end

    def self.search( params = {} )
      query = params[:search-text_field_name_from_form]
      Model.tire.search(load: true, page: params[:page], per_page: 5) do
      query { string query, default_operator: "AND" } if query.present?
    end
  end

您可以更改index_name(应该是唯一的)和分析器

你的控制器就像

def method_name
  @results = Model.search( params ).results
end

您可以在视图中使用@results。希望这可以帮到你。