ElasticSearch / Tire:如何正确设置部分单词搜索

时间:2013-03-12 08:34:31

标签: ruby-on-rails elasticsearch tire

尽管我已经看到许多人提到它相对简单,但我还没有看到它正常工作。假设我有这个:

class Car < ActiveRecord::Base
  settings analysis: {
    filter: {
      ngram_filter: { type: "nGram", min_gram: 3, max_gram: 12 }
    },
    analyzer: {
      partial_analyzer: {
        type: "snowball",
        tokenizer: "standard",
        filter: ["standard", "lowercase", "ngram_filter"]
      }
    }
  } do
    mapping do
      indexes :name,                    index_analyzer: "partial_analyzer"
    end
  end
end

让我们说我有一辆名为“福特”的车,我更新了我的索引。现在,如果我搜索“福特”:

Car.tire.search { query { string "Ford" } }

我的车在我的结果中。现在,如果我寻找“For”:

Car.tire.search { query { string "For" } }

我的车再也找不到了。我认为nGram过滤器会自动为我处理它,但显然它不是。作为临时解决方案,我使用通配符(*)进行此类搜索,但这绝对不是最佳方法,是我搜索中的min_gram和max_gram定义关键元素。谁能告诉我他们是如何解决这个问题的?

我正在使用Rails 3.2.12和ruby 1.9.3。 ElasticSearch版本为0.20.5。

1 个答案:

答案 0 :(得分:5)

您想使用自定义分析器而不是雪球:Elasticsearch custom analyzer

其他分析仪基本上都带有一组预定义的过滤器和标记器。

您可能还想使用Edge-Ngram过滤器:Edge-Ngram filter

Edge-NGram和NGram之间的区别基本上是Edge-Ngram基本上只是坚持一个术语的“边缘”。所以它从前面或后面开始。福特 - &gt; [For]而不是 - &gt; [For,ord]

关于自动填充主题的一些更高级的链接:

Autocompletion with fuzziness (pure elasticsearch, no tire, but very good read)

Another useful question with links provided

修改

基本上我的设置与你的设置非常相似。但是另外还有另一个标题和多场分析器。而且由于支持多语言,这里有一系列名称而不仅仅是名称。

我还指定了search_analyzer,我使用字符串键而不是符号。这就是我实际拥有的:

settings "analysis" => {
    "filter" => {
        "name_ngrams"  => {
            "side"     => "front",
            "max_gram" => 20,
            "min_gram" => 2,
            "type"     => "edgeNGram"
        }
    },
    "analyzer" => {
        "full_name"     => {
            "filter"    => %w(standard lowercase asciifolding),
            "type"      => "custom",
            "tokenizer" => "letter"
        },
        "partial_name"        => {
            "filter"    => %w(standard lowercase asciifolding name_ngrams),
            "type"      => "custom",
            "tokenizer" => "standard"
        }
    }
} do
  mapping do
    indexes :names do
      mapping do
        indexes :name, :type => 'multi_field',
                :fields => {
                    "partial"           => {
                        "search_analyzer" => "full_name",
                        "index_analyzer"  => "partial_name",
                        "type"            => "string"
                    },
                    "title"      => {
                        "type"     => "string",
                        "analyzer" => "full_name"
                    }
                }
      end
    end
  end
end