搜索引擎solr系列---高亮配置及问题总结

版权声明:重在参与,贵在分享 https://blog.csdn.net/wohaqiyi/article/details/78264117

solr的高亮配置有两种方式:

  一种是配置形式,具体是在配置文件中配置的,该方式我没有用过,所以我这里就不写它了。
  另一种就是以代码的形式,我只会用这种方式,所以只写这部分。
  其实还要一种就是自我实现,这个更简单粗暴。

1.高亮的代码具体如下:

package cloud.solr.controller;

import cloud.solr.controller.base.BaseController;
import cloud.solr.domain.Fbf;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by lsf on 2017/10/17.
 */
@RestController
@RequestMapping("/test")
public class TestController extends BaseController {
@RequestMapping(value = "/select",method = RequestMethod.GET)
@CrossOrigin
public Object getById(HttpServletRequest request) {
/**
* http://192.168.1.170:8983/solr/fbf   fbf是solr的一个core名称
*/
long start  = System.currentTimeMillis();
HttpSolrClient solrClient = new HttpSolrClient("http://192.168.1.170:8983/solr/fbf");
SolrQuery query = new SolrQuery();
query.setSort("createtime",SolrQuery.ORDER.asc); //设置排序
String pageNo = request.getParameter("pageNo");  //第几页
String pageSize = request.getParameter("pageSize"); ; //每页多少数据
if(NumberUtils.isNumber(pageNo) && NumberUtils.isNumber(pageSize)){
   int startPage = Integer.valueOf(pageNo);
   int pageNum = Integer.valueOf(pageSize);
   query.setStart((startPage-1)*pageNum);//起始页,这里一定要注意,不能直接把pageNo赋值给start。
   query.setRows(pageNum);//每页显示数量
}
query.setHighlight(true);// 开启高亮组件
query.setHighlightRequireFieldMatch(true);
query.set("hl.fl","fbfmc"); // 高亮的第一种写法字段
//        query.addHighlightField("fbfmc"); //高亮的第一种写法
query.setHighlightSimplePre("<font color='red'>"); //高亮的标签前缀
query.setHighlightSimplePost("</font>");//高亮的标签后缀
query.setHighlightFragsize(150);
String fbfmc = request.getParameter("fbfmc");
query.addHighlightField("fbfbm"); // 高亮字段
StringBuffer buffer = new StringBuffer();
/**第一种查询写法**/
if(!StringUtils.isEmpty(fbfmc)){
   buffer.append("fbfmc:"+fbfmc);
   query.set("q",buffer.toString());
}else{
   query.set("q","*:*");
}
/**第一种查询写法**/

/**第二种查询写法,但是这种查询方式,我配置高亮时失败了,用第一种查询是可以的**/
//        query.set("q","*:*");
//        if(!StringUtils.isEmpty(fbfmc)){
//            query.addFilterQuery("fbfmc:" +fbfmc);
//        }
/**第二种查询写法**/
QueryResponse rsp = null;
try {
   rsp = solrClient.query( query );
} catch (SolrServerException e) {
   e.printStackTrace();
} catch (IOException e) {
   e.printStackTrace();
}
//获取所有高亮的字段
SolrDocumentList results = rsp.getResults();
Map<String,Map<String,List<String>>> highlightresult=rsp.getHighlighting();
System.out.println(results.getNumFound());//查询总条数
List<Fbf> fbfList = rsp.getBeans(Fbf.class);
for(int i=0;i<fbfList.size();i++){
   String poid = fbfList.get(i).getPoid();
   if (highlightresult.get(poid) != null){
       //如果查询结果的fbfmc在高亮map中有结果则进行替换。
       if(highlightresult.get(poid).get("fbfmc") != null){
           fbfList.get(i).setFbfmc(highlightresult.get(poid).get("fbfmc").get(0));
       }
   }
}
Map result = new HashMap<String,Object>();
result.put("totalNum",results.getNumFound());
result.put("fbfList",fbfList);
long end  = System.currentTimeMillis();
System.out.println("Fbf查询消耗时间:"+(end-start)+"ms");
return result;
}
}

2.高亮遇到的问题:

  (1)query.addFilterQuery(“fbfmc:” +fbfmc)查询条件添加和query.addHighlightField(“fbfmc”)高亮字段添加,以这种写法,高亮配置失败。

  这个我不知道其他人是如何配置的,反正我一这么写就失败,暂且认为是这个原因吧,我的解决方式是,
 查询条件改成`query.set(“q”,”fbfmc:”+fbfmc)写法;
(还记得这里的fbfmc如果manage-schema文件中fbfmc是text_ik类型时可以这么写,如果是string则需要在两边加上*)

 高亮字段设置改成query.set("hl.fl","fbfmc")写法(多个字段以逗号隔开); 将这两个地方改成后者,即可配置高亮成功。具体可以先在solr客户端上验证成功再写在代码里。

  (2)如果你要设置的高亮字段是string类型,不是text_ik类型,那么在查询时,你肯定会传入模糊查询符号*,这样查询到结果高亮后,会将该字段全部匹配,比如传入的是0115,结果中是100115符合该查询,那么整个100115会被高亮,因为它是根据你的分词来进行高亮的。所以我感觉高亮并不适合string类型的。如果要想模糊查询又达到高亮,需要自己写,具体看最后。

  (3)高亮对于数字定义成text_ik这种类型,好像可以从前匹配,但是从中间或从最后就无法匹配成功,比如:633330222111,如果输入63333有可能匹配成功,但是输入0222,或者输入1111是无法匹配成功的。

  (4)高亮的显示结果,会按照匹配的频率最高的,放到最前边展示,如果以相邻距离最近设置,这个我不会,我也好想知道如何配置。

3.自定义高亮:

具体场景是,我们领导要求如果输入一个没有空格的字符串则是模糊查询,如果输入俩字符串中间以空格隔开,则相当于是两个条件,这两个就全都匹配下该字段。
这种情况的解决是我将所有的字段都定义为string类型,不适用text_ik,将传入的条件写成query.set("q","fbfmc:*"+fbfmc+“*”) 这种写法,如果是以空格,则后台判断后,进行一次拼接,比如俩条件,那就写成query.set("q","fbfmc:*"+fbfmc+"* OR fbfmc:*"+fbfmc2+"*")注意中间的OR或者AND必须用大写
因为这种场景高亮是无法精确高亮了,所以,我就将查询结果拿到之后,遍历结果,然后匹配fbfmc字段,如果符合则给添加一个标签,

for(Fbf fbf:fbfList){
 if(qwppArray != null){
     for(String qwppStr:qwppArray){       
         if(!StringUtils.isEmpty(fbf.getFbfmc()))
             fbf.setFbfmc(fbf.getFbfmc().replace(qwppStr,"<font color='red'>"+qwppStr+"</font>"));

     }
 }
}

然后再将对象返回,返回结果再加上分页,效率并不影响,还是一样快,其实我觉得solr内部应该也是这样完成高亮的,因为它至少要匹配一下吧?所以速度没问题。

没有更多推荐了,返回首页