【问题标题】:Solr (sunspot) not finding partial word match when suffix includedSolr(太阳黑子)在包含后缀时未找到部分单词匹配
【发布时间】:2014-12-29 13:56:37
【问题描述】:

我正在一个 Rails 应用程序中实现 solr,特别是与成分搜索有关。如果我对“牛肉”或“鸡肉”这样的简单名词进行部分单词匹配,我可以输入从 1 到完整字符串的任意数量的字母,它会找到包含这些单词的成分。当我有一个带后缀的单词时,问题就出现了,例如“eggs”(-s)、“baked”(-ed)或“baking” (-ing)。

我们以“烘焙”为例。我可以搜索“b​​”、“ba”或“bak”来获得任何带有“baking”一词的结果。如果我搜索“baki”、“bakin”或“baking”,则会导致找不到任何结果。

我想知道我的 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)

【问题讨论】:

  • 经过更多搜索后,看起来这与 stemming 有关,尽管我还没有弄清楚我需要更改什么以允许所有“烘焙”、“烘焙”、“烘焙” ", "baki" 等来匹配 "baking potato"。
  • 我想帮助你,不幸的是我是一个java人。我还没有下定决心启动并运行一个 ruby​​ 项目。所以帮助你的加速时间会相当长。你能在 github 上的某个地方设置一个问题被烧毁的项目吗?
  • @cheffe 我看看今天晚些时候/今晚下班后能不能把东西放在一起,谢谢!
  • 这个问题似乎已经在 [这里][1] [1] 得到了回答:stackoverflow.com/questions/9085478/…
  • @Frank 该链接帮助解决了问题,谢谢!如果您将其添加为答案,我很高兴为您提供赏金。具体来说,我必须将我的&lt;analyzer&gt; 配置拆分为单独的indexquery 分析器配置,从索引配置中删除solr.PorterStemFilterFactory,并在查询中将solr.PorterStemFilterFactory 替换为solr.SnowballPorterFilterFactory(和language="English")配置。

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


【解决方案1】:

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

Ingredient.search_by_partial_name('baki*')

【讨论】:

    【解决方案2】:

    您能否发布以下两个查询生成的日志/实际 solr 查询?

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

    查看这些信息会有所帮助,以便准确了解向 Solr 提供的内容以及 Solr 正在尝试做什么。

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

    解决此问题的一种可能方法是设置一个字段,该字段是“fieldType”字符串的成分列表。然后,您可以让您的搜索对该字段进行前缀搜索(或通配符搜索),并能够从“bak”中带回“baking powder”。 Example here

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

    【讨论】:

    • 你说得对,这是一个自动完成搜索。我现在正在工作,但我会在今天/今晚晚些时候跟进您正在寻找的详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    相关资源
    最近更新 更多