在Lucene或Solr中实现高亮的策略


一:功能背景

最近要做个高亮的搜索需求,以前也搞过,所以没啥难度,只不过原来用的是Lucene,现在要换成Solr而已,在Lucene4.x的时候,散仙在以前的文章中也分析过如何在搜索的时候实现高亮,主要有三种方式,具体内容,请参考散仙以前的2篇文章:
第一:在Lucene4.3中实现高亮的方式
http://qindongliang.iteye.com/blog/1953409
第二:在Solr4.3中服务端高亮的方式
http://qindongliang.iteye.com/blog/2034270



二:方案探究

从整体来讲,主要有2种实现方式,第一就是前台展示数据时使用js高亮,第二就是服务端高亮后返回给前台

后端高亮的流程:



前端高亮的流程:




三:优劣分析

后端高亮:
性能:并发量大的情况下,可能对服务器的性能造成一定影响。
可靠性:高,在浏览器禁用js脚本情况下,仍可以正常显示
前端高亮:
性能:由客户端渲染,相对性能稍高
可靠性:低,在浏览器禁用js脚本情况下,高亮失效

四:注意事项

前台高亮时,需要把句子分词后的词组,返回给前台js,便于正则替换,关于把句子分词,可以用lucene也可以用solr,方式分别如下:
在Lucene中:

Java代码 复制代码  收藏代码
  1. /***  
  2.      *   
  3.      * @param analyzer 分词器  
  4.      * @param text  分词句子  
  5.      * @throws Exception  
  6.      */  
  7.     public static void analyzer(Analyzer analyzer,String text)throws Exception{   
  8.                 TokenStream ts = analyzer.tokenStream("name",text);   
  9.                 CharTermAttribute term=ts.addAttribute(CharTermAttribute.class);   
  10.                 ts.reset();   
  11.                 while(ts.incrementToken()){   
  12.                     System.out.println(term.toString());   
  13.                 }   
  14.                 ts.end();   
  15.                 ts.close();   
  16.     }  
/***
	 * 
	 * @param analyzer 分词器
	 * @param text  分词句子
	 * @throws Exception
	 */
	public static void analyzer(Analyzer analyzer,String text)throws Exception{
		        TokenStream ts = analyzer.tokenStream("name",text);
		        CharTermAttribute term=ts.addAttribute(CharTermAttribute.class);
		        ts.reset();
		        while(ts.incrementToken()){
		            System.out.println(term.toString());
		        }
		        ts.end();
		        ts.close();
	}


在solr中,方式1:

Java代码 复制代码  收藏代码
  1. /***  
  2.  * 根据字段类型分词并打印分词结果  
  3.  * @param text  
  4.  */  
  5. public static void showAnalysisType(String text)throws Exception{   
  6.   
  7.     String fieldType="ik";//分词类型  
  8.     //调用服务   
  9.     FieldAnalysisRequest request = new FieldAnalysisRequest("/analysis/field");   
  10.     //设置类型   
  11.     request.addFieldType(fieldType);   
  12.     //设置待分词的句子    
  13.     request.setFieldValue(text);   
  14.     //sc=private static HttpSolrClient sc=new HttpSolrClient("http://localhost:8983/solr/one");  
  15.     //得到结果   
  16.     FieldAnalysisResponse response =request.process(sc);   
  17.     //得到对应的Analysis   
  18.     Analysis as = response.getFieldTypeAnalysis(fieldType);   
  19.     List<String> results = new ArrayList<String>();   
  20.     //使用guava的库,将iteratro对象转换为List对象   
  21.        List<AnalysisPhase> list=Lists.newArrayList(as.getIndexPhases().iterator());   
  22.        //取某一个fitler的分词结果,因为一个fieldtype很有可能配置了多个filter,每一步经过  
  23.        //filter的结果都不一样,所以此处,要指定一个获取分词结果的filter,跟因为有关   
  24.        //所以散仙这里就写list.size-1了,注意此处的值,并不是固定的   
  25.      for(TokenInfo token:list.get(list.size()-1).getTokens()){   
  26.          //得到分词数据结果   
  27.          results.add(token.getText());   
  28.      }   
  29.         
  30. }  
	/***
	 * 根据字段类型分词并打印分词结果
	 * @param text
	 */
	public static void showAnalysisType(String text)throws Exception{
	
		String fieldType="ik";//分词类型
		//调用服务
		FieldAnalysisRequest request = new FieldAnalysisRequest("/analysis/field");
		//设置类型
		request.addFieldType(fieldType);
		//设置待分词的句子 
		request.setFieldValue(text);
		//sc=private static HttpSolrClient sc=new HttpSolrClient("http://localhost:8983/solr/one");
		//得到结果
	    FieldAnalysisResponse response =request.process(sc);
	    //得到对应的Analysis
	    Analysis as = response.getFieldTypeAnalysis(fieldType);
	    List<String> results = new ArrayList<String>();
	    //使用guava的库,将iteratro对象转换为List对象
        List<AnalysisPhase> list=Lists.newArrayList(as.getIndexPhases().iterator());
        //取某一个fitler的分词结果,因为一个fieldtype很有可能配置了多个filter,每一步经过
        //filter的结果都不一样,所以此处,要指定一个获取分词结果的filter,跟因为有关
        //所以散仙这里就写list.size-1了,注意此处的值,并不是固定的
	     for(TokenInfo token:list.get(list.size()-1).getTokens()){
	    	 //得到分词数据结果
	    	 results.add(token.getText());
	     }
	     
	}


在solr中,方式2:

Java代码 复制代码  收藏代码
  1. /***  
  2.      * 根据字段名分词并打印分词结果  
  3.      * @param text  
  4.      */  
  5.     public static void showAnalysis(String text)throws Exception{   
  6.          //此处是字段名   
  7.          String fieldName="cpyName";   
  8.          //固定写法   
  9.          FieldAnalysisRequest request = new FieldAnalysisRequest("/analysis/field");   
  10.          //添加field   
  11.          request.addFieldName(fieldName);   
  12.          //设置需要分词的句子   
  13.          request.setFieldValue(text);   
  14.          //请求solr服务得到结果   
  15.          FieldAnalysisResponse response =request.process(sc);   
  16.          //封装结果,返回,可能供其后续调用的业务处理   
  17.          List<String> results = new ArrayList<String>();   
  18.          //根据字段名获取结果    
  19.          Analysis as=response.getFieldNameAnalysis(fieldName);   
  20.          //使用guava工具包,转iterator为List   
  21.          List<AnalysisPhase> list=Lists.newArrayList(as.getIndexPhases().iterator());   
  22.          //打印分词结果   
  23.          for(TokenInfo token:list.get(list.size()-1).getTokens()){   
  24.              System.out.println(token.getText());   
  25.          }   
  26.             
  27.     }  
/***
	 * 根据字段名分词并打印分词结果
	 * @param text
	 */
	public static void showAnalysis(String text)throws Exception{
		 //此处是字段名
		 String fieldName="cpyName";
		 //固定写法
		 FieldAnalysisRequest request = new FieldAnalysisRequest("/analysis/field");
		 //添加field
		 request.addFieldName(fieldName);
		 //设置需要分词的句子
		 request.setFieldValue(text);
		 //请求solr服务得到结果
	     FieldAnalysisResponse response =request.process(sc);
	     //封装结果,返回,可能供其后续调用的业务处理
	     List<String> results = new ArrayList<String>();
	     //根据字段名获取结果 
	     Analysis as=response.getFieldNameAnalysis(fieldName);
	     //使用guava工具包,转iterator为List
	     List<AnalysisPhase> list=Lists.newArrayList(as.getIndexPhases().iterator());
	     //打印分词结果
	     for(TokenInfo token:list.get(list.size()-1).getTokens()){
	    	 System.out.println(token.getText());
	     }
	     
	}



最后欢迎大家扫码关注微信公众号:我是攻城师(woshigcs),我们一起学习,进步和交流!(woshigcs)
本公众号的内容是有关搜索和大数据技术和互联网等方面内容的分享,也是一个温馨的技术互动交流的小家园,有什么问题随时都可以留言,欢迎大家来访!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值