search - Google 喜欢使用 Solr 自动建议/预先输入(建议关键字/短语)
问题描述
要求
我需要在搜索框中提供类似 google 的建议。Solr 已经是给定的。结果应如下所示:
搜索词Alex
结果Alexander Behling, Alexander Some ...
searchterm cab
results cable, high voltage cable, cable cutter
目的是提供短语作为建议,而不是整个字段或摘录。查询应该不区分大小写,Alex应该有与alex相同的结果,但 searchresult(建议)必须有原始大小写。
建议必须可以按类别过滤,我们在一个索引中包含多个域的结果,结果应该由包含该域的特定字段过滤。contextField仅适用于“AnalyzingInfixLookupFactory 和 BlendedInfixLookupFactory 当前支持此功能,当由 DocumentDictionaryFactory 支持时。”
我尝试了三种方法
1.方法:FreeTextLookupFactory
config (no special schema changes):
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">default</str>
<str name="lookupImpl">FreeTextLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">content</str>
<str name="ngrams">3</str>
<str name="separator"> </str>
<str name="suggestFreeTextAnalyzerFieldType">text_general</str>
</lst>
</searchComponent>
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy" >
<lst name="defaults">
<str name="suggest">true</str>
<str name="suggest.count">10</str>
<str name="suggest.dictionary">default</str>
<str name="echoParams">explicit</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>
这工作得很好,但只提供单个单词。
searchterm Alex
results Alexander, Alexandra ...
优点是索引速度非常高。我试图将它与 ShingleFilter 结合起来,但这不起作用,可能是因为 ShingleFilter 已经是 FreeTextLookupFactory 的一部分。由于 FreeTextLookupFactory 类别不受支持。
2. 方法:带有自定义字段的 BlendedInfixLookupFactory
schema:
<field name="suggest_field" type="text_suggest" indexed="true" stored="true" multiValued="true"/>
<field name="site" type="string" stored="true" indexed="true"/>
<copyField source="content" dest="suggest_field"/>
<fieldType name="text_suggest" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<!--filter class="solr.LowerCaseFilterFactory"/-->
<filter class="solr.TrimFilterFactory"/>
<filter class="solr.ShingleFilterFactory"
minShingleSize="2"
maxShingleSize="4"
outputUnigrams="true"
outputUnigramsIfNoShingles="true"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldType>
config:
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">default</str>
<str name="lookupImpl">BlendedInfixLookupFactory</str>
<str name="blenderType">position_linear</str>
<str name="dictionaryimpl">DocumentDictionaryFactory</str>
<str name="field">suggest_field</str>
<str name="weightField">weight</str>
<str name="suggestAnalyzerFieldType">text_suggest</str>
<str name="queryAnalyzerFieldType">phrase_suggest</str>
<str name="indexPath">suggest</str>
<str name="buildOnStartup">false</str>
<str name="buildOnCommit">false</str>
<bool name="exactMatchFirst">true</bool>
<str name="contextField">site</str>
</lst>
</searchComponent>
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy" >
<lst name="defaults">
<str name="suggest">true</str>
<str name="suggest.count">10</str>
<str name="suggest.dictionary">default</str>
<str name="echoParams">explicit</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>FreeTextLookupFactory
第二种方法导致我的奇怪行为:
searchterm Alex 或 alex
结果无...
searchterm cab
结果cable, cable, voltage cable, cable Accessories, power cable ...
使用相同的字段,某些查询没有搜索结果。对于 <10000 个条目,索引速度已经 > 12 小时。由于应支持 BlendedInfixLookupFactory 和 DocumentDictionaryFactory 类别。但是在查询中使用类别时。http://localhost:8983/solr/magnolia/suggest?wt=json&suggest=true&suggest.q=nym&suggest.cfq=com
结果是空的。字段“site”确实在索引中多次包含值“com”。
3. 使用 HighFrequencyDictionaryFactory 和自定义字段的方法 BlendedInfixLookupFactory
schema:
<field name="suggest_field" type="text_shingle" indexed="true" stored="true" multiValued="true"/>
...
<copyField source="_text_" dest="suggest_field"/>
...
<fieldType name="text_shingle" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<filter class="solr.TrimFilterFactory"/>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_suggestions.txt" format="snowball" />
<!--filter class="solr.EdgeNGramFilterFactory" minGramSize="4" maxGramSize="15"/-->
<filter class="solr.ShingleFilterFactory" minShingleSize="2" maxShingleSize="4" outputUnigrams="false" outputUnigramsIfNoShingles="true" fillerToken=""/>
</analyzer>
</fieldType>
<!-- marc johnen : used for autocomplete-->
<fieldType name="text_suggest" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.TrimFilterFactory"/>
</analyzer>
</fieldType>
config:
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">default</str>
<str name="lookupImpl">BlendedInfixLookupFactory</str>
<str name="dictionaryImpl">HighFrequencyDictionaryFactory</str>
<str name="field">suggest_field</str>
<str name="suggestAnalyzerFieldType">text_suggest</str>
<str name="minPrefixChars">2</str>
<str name="exactMatchFirst">true</str>
<str name="buildOnStartup">false</str>
<str name="buildOnCommit">true</str>
<str name="highlight">false</str>
</lst>
</searchComponent>
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy" >
<lst name="defaults">
<str name="suggest">true</str>
<str name="suggest.count">10</str>
<str name="suggest.dictionary">default</str>
<str name="echoParams">explicit</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>
这种方法的结果非常好,基本上与指定的一样,除了一些重复的短语,因为一些关键字重复,因为它们在开头或结尾有空格,如“电源线”和“电源线”。除此之外还不错。
搜索词Alex
结果Alexander Behling, Alexander Some ...
searchterm cab
结果电缆、高压电缆、电缆剪
<10000 个文档的索引很容易花费一天的时间。但主要问题是不支持 HighFrequencyDictionaryFactory 类别。
询问
我使用的查询如下所示:
http://localhost:8983/solr/magnolia/suggest?wt=json&suggest=true&suggest.q=cab
<str name="contextField">site</str>
在配置中为类别添加 a并&suggest.cfq=com
在适用时添加到查询中。
解决方案
我最终使用了 FreeTextLookupFactory 并为每种语言创建了一个单独的字段和建议器。
推荐阅读
- matlab - 为什么你认为我们希望在类定义中有多个方法块?我也可以有多个属性块吗?
- isabelle - 当证明开始时,我们如何强制 Isabelle 向我们揭示它在 Isar 的后台应用了什么规则?
- python - 是否可以一次或并行安装多个包,而不是在 python 中一个一个安装?
- javascript - 在javascript中读取部分二进制文件而不将整个文件加载到内存中
- django - 在 Django 2.2 中一起使用 Postgres `unnest` 和 `substr`
- file - 搜索和替换后 EmEditor 命令行保存文件的问题
- python - pygame.time.delay() 比 time.sleep() 好吗?
- makefile - 一个先决条件中的目标数量未知?
- ios - ReplayKit2 - 直接从应用程序开始广播
- sql - 如何在 SQL/PostgreSQL 中的两列中获取 MAX 值