1

我仍然做错了什么。有人可以帮助我吗?我想在 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

4 回答 4

1

您可以使用分析 api检查您实际上是如何索引文档的。

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

使用 asciifolding 对您的用例来说是一个不错的选择,它应该返回查询 svíčka 或 svicka 的结果。我想您的设置中只是一个错字:analyser应该是analyzer. 可能该分析器没有像您期望的那样使用。

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

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

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

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

于 2012-10-19T15:56:48.850 回答
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
于 2012-10-20T22:35:49.857 回答
0
  1. 正如@rubish 建议的那样,您的设置/映射符号不正确,请检查https://github.com/karmi/tire/blob/master/lib/tire/model/indexing.rb中的文档(毫无疑问,文档应该更好)

  2. 总是,总是,总是检查索引的映射,看看是否应用了你想要的映射。

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

于 2012-10-22T12:38:25.223 回答
0

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

  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。希望这可以帮助你。

于 2012-12-19T10:34:47.073 回答