我有一个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中执行此操作的提示!
答案 0 :(得分:2)
订购了solr xml选项。你希望词干分析器在ngram过滤器之前出现,这样你就可以使用ngram-ize cooki,而不是阻止c,co等。
以这种方式组合过滤器可能会导致一些奇怪的结果,主要取决于你的词干分析器的侵略性。您绝对应该将词干分析器添加到查询分析器中,但这会使您的自动完成更糟糕。
更好的解决方案:使用copyField创建独立的text_stemmed和text_autocomplete字段。然后在两个字段上使用OR查询进行搜索。
答案 1 :(得分:0)
与Kyle mentions一样,您可能希望为每个不同的用例使用更多的文本字段类型。
以下是我的一个例子:
<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>
使用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