2014-11-02 30 views
2

我正在将solr应用到Rails应用中,具体涉及成分搜索。如果我对一个简单的名词如“牛肉”或“鸡肉”进行部分单词匹配,我可以输入从1到完整字符串的任意数量的字母,并找到包含这些单词的成分。当我有一个词后缀,例如“鸡蛋”(-s),“烘烤”(-ed)或“烘烤”(-ing)时,问题就会起作用。当包含后缀时Solr(太阳黑子)找不到部分词匹配

让我们以“烘焙”为例。我可以搜索“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) 
+0

经过一番更多搜寻,它看起来像这样涉及到[词干](http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters#虽然我还没有弄清楚我需要改变什么才能让所有的“烘烤”,“烤”,“烘烤”,“巴基”等与“烤土豆”相匹配。 – 2014-11-02 23:08:05

+0

我想帮助你,不幸的是我是一个java的家伙。我还没有决定要开始运行Ruby项目。因此,加速时间来帮助你会很高。你可以设置一个项目,在github上的某个地方烧掉这个问题吗? – cheffe 2014-11-17 10:10:07

+0

@cheffe我会看看我能在今天晚些时候/今晚晚些时候把什么东西扔在一起,谢谢! – 2014-11-17 18:49:58

回答

1

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

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

这将有助于查看该信息,准确了解Solr的内容以及Solr正在尝试执行的操作。

编辑:鉴于你想要部分匹配,我假设这是一个“自动完成”类型的搜索,而不是一个标准的全文搜索。如果是这种情况,那么你可能不希望在文本/标记字段上这样做,因为这将包括词干,而不是按照“baki”这样的部分词汇的方式行事。

解决此问题的一种可能方法是有一个字段,它是一个'fieldType'字符串的成分列表。然后你可以让你的搜索做一个前缀搜索(或通配符搜索)该领域,并能够从“bak”带回“发粉”。 Example here

请注意,前缀搜索在字符串字段上效果最好,并且不会从字符串内部进行匹配,只需从头开始。有很多方法可以实现比我所展示的更高级的自动完成功能。

+0

你是对的,这是一个自动完成搜索。我现在在工作,但我会跟进你今天晚上/今晚晚些时候的细节。 – 2014-11-17 18:49:27

1

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

Ingredient.search_by_partial_name('baki*')