当包含后缀时,Solr(太阳黑子)没有找到部分单词匹配

时间:2014-11-02 22:38:53

标签: solr full-text-search sunspot sunspot-rails sunspot-solr

我将solr应用到Rails应用程序中,特别是与成分搜索有关。如果我对一个简单的名词进行部分单词匹配,例如" beef"或者" chicken",我可以输入从1到完整字符串的任意数量的字母,并找到包含这些字的成分。当我有一个带后缀的单词时,问题就会发挥作用,例如" eggs" ( -s ),"烘焙" ( -ed ),或"烘焙" ( -ing )。

我们采取烘焙"举个例子。我可以搜索" b"," ba"或" bak"用"烘焙"这个词得到任何结果返回。如果我搜索" baki"," bakin"或"烘焙",这会导致找不到任何结果。

我想知道我是否在搜索Rails代码时出错了,或者我是否需要在schema.xml文件中编辑某些内容。我的架构是sunspot提供的默认架构。我的模特&搜索代码如下所示。

class Ingredient < ActiveRecord::Base
  validates :name, presence: true, uniqueness: true

  searchable do
    text :name
  end

  def self.search_by_partial_name(name)
    keywords = name.to_s.split(/\s+/).delete_if(&:blank?)

    search = Sunspot.search(self) do
      text_fields do
        keywords.each do |keyword|
          with(:name).starting_with(keyword)
        end
      end
    end

    search.results
  end
end

搜索:

Ingredient.search_by_partial_name('baki')  # => []
Ingredient.search_by_partial_name('bak')   # => [<Ingredient "baking powder">,
                                                 <Ingredient "baking potato">,
                                                 ...]

谢谢!

编辑:以下是有关上述两个示例正在执行的solr查询的日志。

Started GET "/admin/ingredients/search?term=bak" for 127.0.0.1 at 2014-11-23 09:21:01 -0700
Processing by Admin::IngredientsController#search as JSON
  Parameters: {"term"=>"bak"}
  User Load (0.4ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
  SOLR Request (4.9ms)  [ path=select parameters={fq: ["type:Ingredient", "name_text:bak*"], start: 0, rows: 30, q: "*:*"} ]
  Ingredient Load (0.8ms)  SELECT "ingredients".* FROM "ingredients"  WHERE "ingredients"."id" IN (9853, 9858, 10099, 10281, 10289, 10295, 10350, 10498, 10507, 10583, 10733, 10787, 11048, 11148, 11395, 11603, 11634, 11676, 11734, 11863, 12031, 12189, 12268, 12399, 13128, 13577, 13830, 13886, 14272, 14366)
Completed 200 OK in 12ms (Views: 1.3ms | ActiveRecord: 1.1ms | Solr: 4.9ms)

Started GET "/admin/ingredients/search?term=baki" for 127.0.0.1 at 2014-11-23 09:21:22 -0700
Processing by Admin::IngredientsController#search as JSON
  Parameters: {"term"=>"baki"}
  User Load (0.4ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
  SOLR Request (4.5ms)  [ path=select parameters={fq: ["type:Ingredient", "name_text:baki*"], start: 0, rows: 30, q: "*:*"} ]
Completed 200 OK in 7ms (Views: 0.4ms | ActiveRecord: 0.4ms | Solr: 4.5ms)

2 个答案:

答案 0 :(得分:1)

您可以发布由以下两个查询生成的日志/实际solr查询吗?

Ingredient.search_by_partial_name('baki')  # => []
Ingredient.search_by_partial_name('bak')   # => [<Ingredient "baking powder">,

有助于查看这些信息,以确切了解Solr正在提供什么,以及Solr正在尝试做什么。

编辑:鉴于你想要部分匹配,我假设这是一个“自动完成”类型搜索而不是标准的全文搜索。如果是这种情况,那么您可能不希望在文本/标记化字段上执行此操作,因为这将包括词干,而不是按照您对“baki”之类的部分词语的要求进行操作。

解决此问题的一种可能方法是使字段成为“fieldType”字符串的成分列表。然后你可以让你的搜索对该字段进行前缀搜索(或通配符搜索),并能够从“bak”中恢复“发酵粉”。 Example here

请注意,前缀搜索最适用于字符串字段,并且不会从字符串中进行匹配,只是从头开始。有一些方法可以实现比我所示更高级的自动完成功能。

答案 1 :(得分:1)

在搜索查询的末尾添加星号:

Ingredient.search_by_partial_name('baki*')