lucene UnifiedHighlighter高亮组件

在使用solr的时候,默认的高亮方法使用的是hl.method=original。solr6.4以后出现了一个新的高亮方法unifield,可以直接设置hl.method=unified。官方说法推荐使用这个高亮方法,更加灵活可以支持各类查询。在lucene底层这个方法对应的对象就是这个UnifiedHighlighter,但是没有看到关于这个类的使用方法,自己也不是很看懂api的介绍,试了一下用法可以得到高亮的字段信息。
public static UnifiedHighlighter buildHighlighter(IndexSearcher searcher, Analyzer chAnalyzer) {
	PassageFormatter passageFormatter = new DefaultPassageFormatter(LuceneConstant.PRETAG, LuceneConstant.POSTTAG, "...", true);
        PassageScorer score = new PassageScorer();
        UnifiedHighlighter uniHighlighter = new UnifiedHighlighter(searcher, chAnalyzer);
        uniHighlighter.setFormatter(passageFormatter);
        uniHighlighter.setScorer(score);
	return uniHighlighter;
}
PassageFormatter :设置高亮的一些格式,LuceneConstant.PRETAG与LuceneConstant.POSTTAG是我设置的变量,其实就是高亮的前后缀:<font color='red'>与</font>,其他两个参数没弄明白什么意思,暂且按照默认的设置。
PassageScorer :类似于QueryScore,详细介绍也不是很明白。
将UnifiedHighlighter 设置好后就可以得到highlighter对象。获取高亮字段有几个方法,可以单独获取一个高亮字段。也可以获取一组高亮字段:
获取单一字段:
public String[] highlight(String field, Query query, TopDocs topDocs, int maxPassages) throws IOException {
    Map<String, String[]> res = highlightFields(new String[]{field}, query, topDocs, new int[]{maxPassages});
    return res.get(field);
  }
获取多个字段:
public Map<String, String[]> highlightFields(String[] fields, Query query, TopDocs topDocs, int[] maxPassages)
      throws IOException {
    final ScoreDoc scoreDocs[] = topDocs.scoreDocs;
    int docids[] = new int[scoreDocs.length];
    for (int i = 0; i < docids.length; i++) {
      docids[i] = scoreDocs[i].doc;
    }
    return highlightFields(fields, query, docids, maxPassages);
  }
我们在使用的时候,可以将需要的高亮字段建立一个数组,直接调用highlighter.highlightFields方法就可以得到高亮字段的Map集合,遍历Map集合就可以获取对应的字段值。但是这个地方需要注意的是Map里面key值存的是字段的名称,value存的是命中条数对应的字段内容的数组集合。也就是说你设置了四个高亮字段,搜索命中了10条数据,返回的高亮Map集合的大小就是4,但是每一个key对应的value数组大小是10,所以在获取每一个命中目标对应的字段内容时,需要对topDocs遍历:
public SearchResult convertResult(TopDocs topDocs,BooleanQuery booleanQuery,IndexSearcher searcher) 
throws IOException, InvalidTokenOffsetsException{
	Analyzer chAnalyzer = new IndexPinyinAnalyzer(false);
	ScoreDoc[] scoreDocs = topDocs.scoreDocs;
	QueryScorer scorer = new QueryScorer(booleanQuery);  
	//设定高亮显示的格式
        UnifiedHighlighter uniHighlighter = LuceneUtil.buildHighlighter(searcher, chAnalyzer);
        String[] highField = LuceneUtil.buildHighFields();
        Map<String,String[]> contentHigh = uniHighlighter.highlightFields(highField, booleanQuery, topDocs);
        for (int i = 0; i < scoreDocs.length ; i++) {  
        	SearchItem item=new SearchItem();
            	Document doc = searcher.doc(scoreDocs[i].doc); 
		//contentHigh.get("content")获取到的是content字段命中的所有条数的value 的数组,
		遍历后直接取对应的i项就是这条命中的content字段的value值,不明白可以打个断点看一下Map里面的结构
		if(null==contentHigh.get("content")[i]) {
			item.setHlText(doc.get("content"));
		}else {
        		item.setHlText(contentHigh.get("content")[i]); 
        	}
//....获取其他字段类似
 }
}
但是我在获取到高亮数据后的一个问题时就是,我所有字段设置了FieldType为:
	FieldType type = new FieldType(TextField.TYPE_STORED);
        type.setStoreTermVectorOffsets(true);//记录相对增量
        type.setStoreTermVectorPositions(true);//记录位置信息
        type.setStoreTermVectors(true);//存储向量信息
        type.freeze();//阻止改动信息
才会返回正确的高亮信息,其他没有设置过得只返回普通数据,没有高亮,这个不知道是什么原因,看官方的介绍:
A Highlighter that can get offsets from either postings (IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS), term vectors (FieldType.setStoreTermVectorOffsets(boolean)), or via re-analyzing text.
好像是必须设置type才可以,但是在solr中使用时好像都可以正常高亮,期待大神解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值