solr 6.5 suggest 自动补全(解决单个字符无结果问题)

solr的日常搜索大家都比较熟悉,稍微提升点的搜索就涉及到了自动补全。下面就亲身测试,说一下自动补全,使用的为solr 6.5版本。


在原有的solr搜索基础上增加自动补全,首先修改solrconfig.xml
searchComponent 为官方wiki的代码,无改动。

<searchComponent class="solr.SpellCheckComponent" name="suggest">  
        <str name="queryAnalyzerFieldType">text_spell</str>  
        <lst name="spellchecker">  
            <str name="name">suggest</str>  
            <str name="classname">org.apache.solr.spelling.suggest.Suggester</str>  
            <str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str>  
            <str name="field">suggestion</str>  
            <!-- the indexed field to derive suggestions from -->  
            <float name="threshold">0.0001</float>  
            <str name="spellcheckIndexDir">spellchecker</str>  
            <str name="comparatorClass">freq</str>  
            <str name="buildOnOptimize">true</str>  
            <!--<str name="buildOnCommit">true</str>-->  
        </lst>  
    </searchComponent>  
    <requestHandler class="org.apache.solr.handler.component.SearchHandler"  
                    name="/suggest">  
        <lst name="defaults">  
            <str name="spellcheck">true</str>  
            <str name="spellcheck.dictionary">suggest</str>  
            <str name="spellcheck.onlyMorePopular">true</str>  
            <str name="spellcheck.extendedResults">false</str>  
            <str name="spellcheck.count">10</str>  
            <str name="spellcheck.collate">true</str>  
        </lst>  
        <arr name="components">  
            <str>suggest</str>  
        </arr>  
    </requestHandler>  
      
     <queryConverter name="phraseQueryConverter" class="org.apache.solr.spelling.SpellingQueryConverter"/>  
名称 含义
queryAnalyzerFieldType schema.xml中的fieldType类型,如果加了这个选项,拼写检查时会调用这个fieldType的分词器,如果没有加,solr会取field属性上面filetype的分词器,这个时候还找不到,solr会创建一个按空格进行分词(SpellCheckComponent需要一个分词器才能运行),在这们项目中,我们现希望Analyzer不对查询做任何的改变,因此选择string。(网上也建议不要对他定义复杂的分词,如果指定的Analyzer很复杂的话,会导致suggest返回的结果不符合预期)
name 就是取个名字,江湖中的人士都是让他等于suggest
classname org.apache.solr.spelling.suggest.Suggester(不要改动)
lookupImpl org.apache.solr.spelling.suggest.tst.TSTLookup(不要改动)
field 说明只在这个字段上面做拼写检查
threshold 限制一些不常用的词出现,值越大过滤词就越多,取值范围【0~1】官网默认是0.005
comparatorClass ellchecker组件中的comparatorClass参数可配置Suggest返回结果的排序,目前有如下几种可选方案:1.Empty – in which case the default is used. 默认就是这个;2.score – explicitly choose the default case ;3.freq – Sort by frequency first, then score. 通过频率的第一排序,然后得分 (开发时用这个);4.A fully qualified class name – Provide a custom comparator that implements Comparator
buildOnCommit 取值true或者flase当commit的时候,对拼写检查索引进行构建。(只有构建后,拼写检查才有效果)
buildOnOptimize 当optimize的时候,对拼写检查索引进行构建。(只有构建后,拼写检查才有效果)

requestHandler参数含义:

代码 含义
spellcheck 开启检查建议
spellcheck.dictionary 必须与searchComponent中spellchecker标签下suggest配置对应
spellcheck.count 配置拼写检查提示结果的个数(可以根据需要适当加大)
spellcheck.onlyMorePopular 等于true,可以根据权重排序,开发时我一般让他等于true
spellcheck.collate 提供一个查询并与第一个匹配的建议,solr 6.5 suggest 自动补全(解决单个字符无结果问题)
components handler拥有的 components,first-components,last-components这三个属性的剖析Solr的handler都是同过这三个属性来取他所依赖的components(组件)备注:handler在运行时,会加载5个默认的组件1.如果配置了components,则SOlr不会运行默认的5个组件。而且你配置的first-components,last-components两个都是无效的。2.如果配置了first-components,SOlr会给handler添加5个默认的组件时,同时会添加first-components配置的组件,而且这个组件最先工作。3.同上,只不过放在最后工作

managed-schema修改

<!-- 单词补全建议-->
    
	<fieldType name="text_spell" class="solr.TextField">  
      <analyzer type="index">  
        <tokenizer class="solr.StandardTokenizerFactory"/>  
        <filter class="solr.LowerCaseFilterFactory"/>  
      </analyzer>  
      <analyzer type="query">  
        <tokenizer class="solr.StandardTokenizerFactory"/>  
        <filter class="solr.LowerCaseFilterFactory"/>  
      </analyzer>  
    </fieldType>
 <!-- 完整词组建议  --> 
  <fieldType class="solr.TextField" name="text_auto_phrase">
     <analyzer>
   	<tokenizer class="solr.KeywordTokenizerFactory"/>
          <filter class="solr.LowerCaseFilterFactory"/>
     </analyzer>
  </fieldType>

<field name="suggestion"      type="text_auto_phrase"      indexed="true"      stored="true"      termVectors="true" multiValued="true" />

<copyField source="keyword"   dest="suggestion" />

到这配置就完成了。

配置好后,重启solr,导入数据
solr 6.5 suggest 自动补全(解决单个字符无结果问题)
然后输入suggest
solr 6.5 suggest 自动补全(解决单个字符无结果问题)

solr 6.5 suggest 自动补全(解决单个字符无结果问题)

输入单个字符或单个汉字无结果显示解决

查村时加上字段名就可以支持单个字符了

solr 6.5 suggest 自动补全(解决单个字符无结果问题)

程序调用

/**
	 *
	 * 自动建议
	 * @param keyword 格式为:key:value
	 * @return
	 * @author john
	 * @version 2019年2月26日
	 */
	protected JSONObject suggest(String keyword) {
		QueryResponse resp;
		Map<String,List<String>> map=new LinkedHashMap<>();
		String collatedResult="";
		try {
		    //获得solr连接客户端的代码请自查百度
			HttpSolrClient httpSolrClient = getHttpSolrClient();
			SolrQuery query = new SolrQuery(keyword);
			resp = httpSolrClient.query(query);
			SpellCheckResponse spellCheckResponse = resp.getSpellCheckResponse();
			Map<String, SpellCheckResponse.Suggestion> suggestionMap = spellCheckResponse.getSuggestionMap();
			for (String key:suggestionMap.keySet()){
				SpellCheckResponse.Suggestion suggestion = suggestionMap.get(key);
				map.put(key,suggestion.getAlternatives());
			}
			collatedResult = spellCheckResponse.getCollatedResult();
			if (StringUtils.isNotBlank(collatedResult)&&collatedResult.indexOf(":")>-1){
				collatedResult=collatedResult.substring(collatedResult.indexOf(":")+1);
			}
		} catch (Exception e) {
			e.printStackTrace();
			LogUtils.writeErrLog("SolrBaseSupport", e.getClass().getSimpleName(), "queryCount", e.toString());
		}
		JSONObject object=new JSONObject();
		object.put("suggestions",map);
		object.put("recommend",collatedResult);
		return object;
	}

字段说明参考:https://blog.csdn.net/dandan2zhuzhu/article/details/52025656