在Sunspot / Solr中查找单词的单数形式

时间:2011-12-21 21:47:21

标签: ruby-on-rails ruby solr sunspot

我有一个Rails + Sunspot应用程序,我正在配置它,以便搜索返回查询的单个版本。例如:

我想搜索“cookies”以返回名为“cookie”的内容。目前我的太阳黑子搜索返回“cookies”而不是“cookie”(singluar)。

我已经对Solr的schema.xml进行了一些自定义,添加了solr.EdgeNGramFilterFactory以提供更多的灵活性,但EdgeNGramFilterFactory不适用于这种情况,因为它只在查询是结果名称的子字符串时才允许匹配。我的理解是EdgeNGramFilterFactory将在用户搜索“co”,“coo”,“cook”或“cooki”时返回“cookie”,但不会返回“cookie”的超级字符串(即:cookies)。简单地说,这是因为“cookies”不是“cookie”中的子串。

我已经尝试添加所有三个Solr的内置词干工厂,但无济于事。您可以在我的架构中看到一个已注释掉的内容。

在schema.xml中,相关字段如下所示:

<fieldType name="text" class="solr.TextField" omitNorms="false">
  <analyzer type="index">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StandardFilterFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
    <!-- <filter class="solr.EnglishMinimalStemFilterFactory"/> -->
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StandardFilterFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

我认为我可以清楚地说明用户的查询,但我不想在它遇到Solr之前触摸他们的查询。

你可以在这里玩这个:http://staging.zisboombah.com/parent/food_guide/?search=cookie。尝试更改“cookie”和“cookies”之间的查询。

非常感谢任何有关如何在Solr中执行此操作的提示!

2 个答案:

答案 0 :(得分:2)

订购了solr xml选项。你希望词干分析器在ngram过滤器之前出现,这样你就可以使用ngram-ize cooki,而不是阻止c,co等。

以这种方式组合过滤器可能会导致一些奇怪的结果,主要取决于你的词干分析器的侵略性。您绝对应该将词干分析器添加到查询分析器中,但这会使您的自动完成更糟糕。

更好的解决方案:使用copyField创建独立的text_stemmed和text_autocomplete字段。然后在两个字段上使用OR查询进行搜索。

答案 1 :(得分:0)

与Kyle mentions一样,您可能希望为每个不同的用例使用更多的文本字段类型。

以下是我的一个例子:

schema.xml

<schema>
  <types>

    <fieldType name="text" class="solr.TextField" omitNorms="false">
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StandardFilterFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>

    <fieldType name="text_en" class="solr.TextField" omitNorms="false">
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StandardFilterFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.PorterStemFilterFactory"/>
      </analyzer>
    </fieldType>

    <fieldType name="text_stopwords" class="solr.TextField" omitNorms="false">
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StandardFilterFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
      </analyzer>
    </fieldType>

    <!-- ... -->
  </types>
  <fields>
    <!-- ... -->
  </fields>

  <copyField source="*_text"   dest="text"/>
  <copyField source="*_texts"  dest="text"/>
  <copyField source="*_textsv" dest="text"/>
  <copyField source="*_textv"  dest="text"/>

</schema>

Sunspot modeling

使用copyField指令可以在模型中保存一些设置工作。但是,Sunspot使用这些text声明来决定keywords哪些字段 - 默认情况下搜索,因此我希望包含使用text指定完整Solr的不同:as次调用文件字段名称。

searchable do
  text :name, stored: true, default_boost: 10
  text :name, as: 'name_text_en'
  text :description, stored: true
end