![]()
Lucene的Hightlight模块可以高亮搜索结果中的关键字,给搜索引擎自定义界面的自由。
如何创建Highlighter
为了创建一个Highlighter,需要一个Formatter和一个Scorer,如下所示:
Highlighter highlighter = new Highlighter(new SimpleHTMLFormatter("<font color='red'>", "</font>"), new QueryScorer(query));
如何高亮
有多种接口,只举最简单的一个,需要Analyzer,fieldName和fieldContent:
highlighter.getBestFragment(analyzer, fieldName, fieldContent)
如何控制结果的长度
通过设置Fragmenter的长度即可实现:
Fragmenter fragmenter = new SimpleFragmenter(fragmentSize); highlighter.setTextFragmenter(fragmenter);
完整的例子
package com.hankcs;
import org.ansj.lucene4.AnsjAnalysis;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import java.io.IOException;
/**
* 演示高亮搜索结果
* @author hankcs
*
*/
public class HighLighterDemo
{
public static void main(String[] args)
{
// Lucene Document的主要域名
String fieldName = "text";
// Lucene版本
Version ver = Version.LUCENE_48;
// 实例化Analyzer分词器
Analyzer analyzer = new AnsjAnalysis();
Directory directory = null;
IndexWriter iwriter;
IndexReader ireader = null;
IndexSearcher isearcher;
try
{
//索引过程**********************************
//建立内存索引对象
directory = new RAMDirectory();
//配置IndexWriterConfig
IndexWriterConfig iwConfig = new IndexWriterConfig(ver, analyzer);
iwConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
iwriter = new IndexWriter(directory, iwConfig);
{
// 加入一个文档
Document doc = new Document();
doc.add(new TextField(fieldName, "我白天是一名语言学习者,晚上是一名初级码农。空的时候喜欢看算法和应用数学书,也喜欢悬疑推理小说,ACG方面喜欢型月、轨迹。喜欢有思想深度的事物,讨厌急躁、拜金与安逸的人。目前在魔都某女校学习,这是我的个人博客。闻道有先后,术业有专攻,请多多关照。你喜欢写代码吗?", Field.Store.YES));
doc.add(new TextField("title", "关于hankcs", Field.Store.YES));
iwriter.addDocument(doc);
}
{
// 再加入一个
Document doc = new Document();
doc.add(new TextField(fieldName, "程序员喜欢黑夜", Field.Store.YES));
doc.add(new TextField("title", "关于程序员", Field.Store.YES));
iwriter.addDocument(doc);
}
iwriter.close();
//搜索过程**********************************
//实例化搜索器
ireader = DirectoryReader.open(directory);
isearcher = new IndexSearcher(ireader);
String keyword = "喜欢";
//使用QueryParser查询分析器构造Query对象
QueryParser qp = new QueryParser(ver, fieldName, analyzer);
Query query = qp.parse(keyword);
System.out.println("Query = " + query);
//搜索相似度最高的5条记录
TopDocs topDocs = isearcher.search(query, 5);
System.out.println("命中:" + topDocs.totalHits);
//输出结果
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (int i = 0; i < Math.min(5, scoreDocs.length); ++i)
{
Document targetDoc = isearcher.doc(scoreDocs[i].doc);
System.out.print(targetDoc.getField("title").stringValue());
System.out.println(" , " + scoreDocs[i].score);
String text = targetDoc.get(fieldName);
System.out.println(displayHtmlHighlight(query, analyzer, fieldName, text, 200));
}
}
catch (CorruptIndexException e)
{
e.printStackTrace();
}
catch (LockObtainFailedException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (ParseException e)
{
e.printStackTrace();
}
catch (InvalidTokenOffsetsException e)
{
e.printStackTrace();
}
finally
{
if (ireader != null)
{
try
{
ireader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (directory != null)
{
try
{
directory.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
/**
* 获取高亮显示结果的html代码
* @param query 查询
* @param analyzer 分词器
* @param fieldName 域名
* @param fieldContent 域内容
* @param fragmentSize 结果的长度(不含html标签长度)
* @return 结果(一段html代码)
* @throws IOException
* @throws InvalidTokenOffsetsException
*/
static String displayHtmlHighlight(Query query, Analyzer analyzer, String fieldName, String fieldContent, int fragmentSize) throws IOException, InvalidTokenOffsetsException
{
//创建一个高亮器
Highlighter highlighter = new Highlighter(new SimpleHTMLFormatter("<font color='red'>", "</font>"), new QueryScorer(query));
Fragmenter fragmenter = new SimpleFragmenter(fragmentSize);
highlighter.setTextFragmenter(fragmenter);
return highlighter.getBestFragment(analyzer, fieldName, fieldContent);
}
}
输出结果
Query = text:喜欢 命中:2 关于程序员 , 0.2972674 程序员<font color='red'>喜欢</font>黑夜 关于hankcs , 0.124633156 我白天是一名语言学习者,晚上是一名初级码农。空的时候<font color='red'>喜欢</font>看算法和应用数学书,也<font color='red'>喜欢</font>悬疑推理小说,ACG方面<font color='red'>喜欢</font>型月、轨迹。<font color='red'>喜欢</font>有思想深度的事物,讨厌急躁、拜金与安逸的人。目前在魔都某女校学习,这是我的个人博客。闻道有先后,术业有专攻,请多多关照。你<font color='red'>喜欢</font>写代码吗?
在HTML下观看:
Query = text:喜欢
命中:2
关于程序员 , 0.2972674
程序员喜欢黑夜
关于hankcs , 0.124633156
我白天是一名语言学习者,晚上是一名初级码农。空的时候喜欢看算法和应用数学书,也喜欢悬疑推理小说,ACG方面喜欢型月、轨迹。喜欢有思想深度的事物,讨厌急躁、拜金与安逸的人。目前在魔都某女校学习,这是我的个人博客。闻道有先后,术业有专攻,请多多关照。你喜欢写代码吗?
码农场
代码框中右侧隐藏的代码看不到啊
hi,请问下你知道lucene高亮用的是什么算法吗?有没有独立于lucene的高亮算法实现?
请问需要导入哪些jar包