原文地址: http://blog.csdn.net/javaman_chen/article/details/8224407
Lucene针对高亮显示功能提供了两种实现方式,分别是Highlighter和FastVectorHighlighter。
顾名思义,FastVectorHighlighter较Highlighter速度更快,功能也更强大,但是有使用前提:创建索引时,需要存储Field的分词向量信息。(TermVector.WITH_POSITIONS_OFFSETS),而Highlighter则不需要,如何在时间和空间上进行取舍,需要开发人员自己衡量
Lucene处理高亮显示的大概流程如下:
1.首先获取原始文档的TokenStream
原始文档可打到索引里(通过Store.YES属性),也可从其他物理媒介中获取(考虑到Lucene的存储性能不是很高效)
高亮显示功能需要知道每一个Term的位置和偏移量信息,在索引库中这些信息是通过分词向量(TermVector)来存储的,因此在创建索引阶段,如果为索引域指定TermVector.WITH_POSITIONS_OFFSETS属性,则可以加快TokenStream的获取过程,否则需要通过Analyzer去重新解析获取
Lucene提供了TokenSources这个实用类,通过它提供的静态方法,可以很方便的获取到文档的TokenStream信息:
TokenSources.getAnyTokenStream(reader, docId, field, analyzer);//方法体中会先通过TermVector获取TokenStream,TermVector不存在,通过analyzer获取
该方法的使用前提是创建索引时指定了Store.YES信息,如不指定该信息,可通过Analyzer.tokenStream(field, new StringReader(String text))方法来获取text的TokenStream。
2.将原始文档进行切片处理
当原始文档信息量较大时,我们可能只需要高亮出局部有价值的信息,而将其他的冗余信息过滤掉,这个时候就需要对原始信息进行切片处理,选出最有价值的切片来进行加工。
NullFragmenter:不进行切片处理,保留原始文档的所有字符
SimpleFragmenter:按指定字符长度将文档进行分割(默认字符长度是100)
SimpleSpanFragmenter:功能同SimpleFragmenter类似,但不会将SpanQuery或PhraseQuery的查询结果打散。
3.选出最符合搜索条件的文档切片
Lucene提供了QueryScorer和SpanScorer类来对每一个切片进行评分
在Lucene实战一书中,作者建议我们使用SimpleSpanFragmenter+SpanScorer的组合方式,但在3.6版本的测试中SpanScorer视乎不再适用(个人没搞清楚怎样使用)
4.将最后选定的文档片段进行编码处理
5.格式化显示编码之后的文档片段信息(加粗、改变字体颜色等等。。。)
Highlighter使用示例:
//首先获取docId的TokenStream
TokenStream tokenStream=TokenSources.getAnyTokenStream(reader, docId, field, analyzer);
//构建Fragmenter对象,用于文档切片
Fragmenter fragmenter = new SimpleFragmenter(100);//默认字符为100
//构建Scorer,用于选取最佳切片
Scorer fragmentScore = new QueryScorer(query);
//构建Formatter格式化最终显示(将字体颜色设置为红色)
Formatter formatter = new SimpleHTMLFormatter("<font color='red'>","</font>");
//实例化Highlighter组件
Highlighter highlighter = new Highlighter(formatter,fragmentScore);
highlighter.setTextFragmenter(fragmenter);
// 最后一步,获取hightlightText
highlighter.getBestFragment(tokenStream, text);//第二个参数为原始文档信息
//构造Highlighter组件
FragListBuilder fragListBuilder = new SimpleFragListBuilder();
FragmentsBuilder fragmentBuilder =new ScoreOrderFragmentsBuilder(BaseFragmentsBuilder.COLORED_PRE_TAGS,BaseFragmentsBuilder.COLORED_POST_TAGS);
FastVectorHighlighter highligher=new FastVectorHighlighter(true, true,fragListBuilder, fragmentBuilder);
//构造FieldQuery
Query query=new QueryParser(...).parse(...);
FieldQuery fieldQuery = highlighter.getFieldQuery(query);
//高亮最佳文档切片
highlighter.getBestFragment(fieldQuery, IndexReader reader, int docId, String field, int fragCharSize);//fragCharSize需要大于18
注意:使用FastVectorHighlighter,在创建索引时,必须要为field指定TermVector.WITH_POSITIONS_OFFSETS和Store.YES属性