Solr 部分和完整字符串匹配
Posted
技术标签:
【中文标题】Solr 部分和完整字符串匹配【英文标题】:Solr Partial And Full String Match 【发布时间】:2011-06-17 00:47:53 【问题描述】:我正在尝试允许在 Solr 中搜索部分字符串,因此如果有人搜索“ppopota”,他们会得到与搜索“河马”相同的结果。我上下阅读了文档,感觉自己已经用尽了所有选择。到目前为止,我有以下内容:
定义一个新的字段类型:
<fieldtype name="testedgengrams" class="solr.TextField">
<analyzer>
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
</analyzer>
</fieldtype>
定义“testedgengrams”类型的字段:
<field name="text_ngrams" type="testedgengrams" indexed="true" stored="false"/>
将 text_ngrams 的内容复制到文本中:
<copyField source="text_ngrams" dest="text"/>
唉,这行不通。我错过了什么?
【问题讨论】:
交叉发布:mail-archive.com/solr-user@lucene.apache.org/msg46563.html 【参考方案1】:您正在使用EdgeNGramFilterFactory 生成标记“hi”、“hip”、“hipp”等,因此它不会匹配“ppopota”。请改用 NGramFilterFactory。
【讨论】:
很好,但这并没有帮助。我也尝试将 text_ngrams 的内容复制到这样的文本中:启用部分单词搜索
您必须编辑本地 schema.xml 文件,通常在 solr/config 下,以添加:
-
NgramFilterFactory
EdgeNGramFilterFactory
这是我的样子:sample solr schema.xml
这是要粘贴的行:
<filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
EdgeNGram
我选择了 EdgeN 选项。它不允许在单词中间进行搜索,但允许从单词的开头开始进行部分单词搜索。这大大减少了您不想要的误报/匹配,表现更好,并且通常不会被用户错过。另外,我喜欢 minGramSize=2 所以你必须输入至少 2 个字符。有些人将此设置为 3。
一旦你的本地设置和工作,你必须编辑 websolr 使用的 schema.xml,否则即使你为你的模型配置了全文搜索,你也会得到需要输入全词的默认行为。
更上一层楼
5 ways to speed up indexing
使用 Heroku 编辑 websolr schema.xml 的特殊说明
-
转到您应用的 Heroku 在线仪表板
转到资源选项卡,然后单击 Websolr 插件
点击索引下的默认链接
点击高级配置链接
从本地粘贴您的 schema.xml,包括您选择的 Ngram 标记器的配置(如上所述)。保存。
复制“配置您的 Heroku 应用程序”框中的链接,然后将其粘贴到终端中以在您的 heroku 配置中设置您的 WEBSOLR_URL 链接。
点击“索引状态”链接获取漂亮的统计信息,看看您的运行速度是快还是慢。
重新索引所有内容
不要使用 heroku run rake sunspot:solr:reindex - 它已被弃用,不接受任何参数,而且速度较慢 默认批量大小为 50,大多数人建议使用 1000,但我发现通过将其提高到 5000+,结果明显更快(每秒 1000 行,而不是大约 500 rps)heroku 运行 rake 太阳黑子:reindex[5000]
【讨论】:
但是这个问题和 Heroku 有什么关系呢? O_o 好点子,巴巴吉德。我在自己的世界里,每个人的配置都和我一样。编辑答案。 谢谢亚伦。部分 Solr 搜索把我逼疯了。 @AaronHenderson 指向“加快索引速度的 5 种方法”的链接已损坏。你有更新的链接吗?【参考方案3】:好的,我正在对字段名做同样的事情
name_de
我设法使用这样的 copyField 让这个东西工作:
schema.xml
<schema name="solr-magento" version="1.2">
<types>
...
<fieldType name="type_name_de_partial" class="solr.TextField">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="1000" side="front" />
<filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="1000" side="back" />
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.TrimFilterFactory" />
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="German" protected="protwords_de.txt"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.TrimFilterFactory" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.SnowballPorterFilterFactory" language="German" protected="protwords_de.txt"/>
</analyzer>
</fieldType>
</types>
...
<fields>
...
<field name="name_de_partial" type="type_name_de_partial" indexed="true" stored="true"/>
</fields>
....
<copyField source="name_de" dest="name_de_partial" />
</schema>
然后在solrconfig.xml中创建搜索条件
<requestHandler name="magento_de" class="solr.SearchHandler">
<lst name="defaults">
<str name="defType">dismax</str>
<str name="echoParams">explicit</str>
<str name="tie">0.01</str> <!-- Tie breaker -->
<str name="qf">name_de_partial^1.0 name_de^3.0</str> <!-- Phrase Fields -->
<str name="pf">name_de_partial^1.0 name_de^3.0</str> <!-- Phrase Fields -->
<str name="mm">3<90%</str> <!-- Minimum 'Should' Match [id 1..3 must much all, else 90proc] -->
<int name="ps">100</int> <!-- Phrase Slop -->
<str name="q.alt">*:*</str>
..
</lst>
<arr name="last-components">
<str>spellcheck</str>
</arr>
</requestHandler>
使用这个 solr 正在使用 pow 1.0 搜索字段 name_de_partial 和使用 pow 3.0 在 name_de 中搜索
因此,如果引擎在 name_de 中找到特定的查询词,则将其放在列表的顶部。 如果他也在 name_de_partial 中找到了一些东西,那么它也会被计算在内并被放入结果中。
并且字段 name_de_partial 正在使用特定的 solr 过滤器,因此它可以使用查询“hip”或“ppie”或“ippi”找到单词“hippie”而无需 swet。
【讨论】:
【参考方案4】:如果您在索引和查询时都设置 EdgeNGramFilterFactory 或 NGramFilterFactory,结合 q.op=AND(或者如果您使用 dismax,则默认 mm=100%)您会遇到一些问题。
尝试仅在索引时定义 NGramFilterFactory:
<fieldType name="testedgengrams" class="solr.TextField">
<analyzer type="index">
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="15"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
</analyzer>
</fieldType>
或尝试设置 q.op=OR(如果您使用 dismax,则设置 mm=1)
【讨论】:
谢谢你,解决了我遇到的一个问题。以上是关于Solr 部分和完整字符串匹配的主要内容,如果未能解决你的问题,请参考以下文章