【Lucene】Apache Lucene全文检索引擎架构之中文分词和高亮显示4
前面总结的都是使用Lucene的标准分词器,这是针对英文的,但是中文的话就不顶用了,因为中文的语汇与英文是不同的,所以一般我们开发的时候,有中文的话肯定要使用中文分词了,这一篇博文主要介绍一下如何使用smartcn中文分词器以及对结果的高亮显示。
1. 中文分词
使用中文分词的话,首先到添加中文分词的jar包。
<!-- lucene中文分词器 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>5.3.1</version>
</dependency>
然后弄一些数据,使用中文分词器来生成一下索引,以便于后面搜索用到。
public class Indexer {
private Directory dir; //存放索引的位置
//准备一下用来测试的数据
private Integer ids[] = {1, 2, 3}; //用来标识文档
private String citys[] = {"上海", "南京", "青岛"};
private String descs[] = {
"上海是个繁华的城市。",
"南京是一个有文化的城市。",
"青岛是一个美丽的城市。"
};
//生成索引
@Test
public void index(String indexDir) throws Exception {
dir = FSDirectory.open(Paths.get(indexDir));
IndexWriter writer = getWriter();
for(int i = 0; i < ids.length; i++) {
Document doc = new Document();
doc.add(new IntField("id", ids[i], Field.Store.YES));
doc.add(new StringField("city", citys[i], Field.Store.YES));
doc.add(new TextField("desc", descs[i], Field.Store.YES));
writer.addDocument(doc); //添加文档
}
writer.close(); //close了才真正写到文档中
}
//获取IndexWriter实例
private IndexWriter getWriter() throws Exception {
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();//使用中文分词器
IndexWriterConfig config = new IndexWriterConfig(analyzer); //将标准分词器配到写索引的配置中
IndexWriter writer = new IndexWriter(dir, config); //实例化写索引对象
return writer;
}
public static void main(String[] args) throws Exception {
new Indexer().index("D:\\lucene2");
}
}
建立好了索引,接下来就是查询了。
public class Searcher {
public static void search(String indexDir, String q) throws Exception {
Directory dir = FSDirectory.open(Paths.get(indexDir)); //获取要查询的路径,也就是索引所在的位置
IndexReader reader = DirectoryReader.open(dir);
IndexSearcher searcher = new IndexSearcher(reader);
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer(); //使用中文分词器
QueryParser parser = new QueryParser("desc", analyzer); //查询解析器
Query query = parser.parse(q); //通过解析要查询的String,获取查询对象
long startTime = System.currentTimeMillis(); //记录索引开始时间
TopDocs docs = searcher.search(query, 10);//开始查询,查询前10条数据,将记录保存在docs中
long endTime = System.currentTimeMillis(); //记录索引结束时间
System.out.println("匹配" + q + "共耗时" + (endTime-startTime) + "毫秒");
System.out.println("查询到" + docs.totalHits + "条记录");
for(ScoreDoc scoreDoc : docs.scoreDocs) { //取出每条查询结果
Document doc = searcher.doc(scoreDoc.doc); //scoreDoc.doc相当于docID,根据这个docID来获取文档
System.out.println(doc.get("city"));
System.out.println(doc.get("desc"));
String desc = doc.get("desc");
}
reader.close();
}
public static void main(String[] args) {
String indexDir = "D:\\lucene2";
String q = "上海繁华"; //查询这个字符
try {
search(indexDir, q);
} catch (Exception e) {
e.printStackTrace();
}
}
}
看一下查询结果:
匹配上海繁华共耗时15毫秒
查询到1条记录
上海
上海是个繁华的城市。
2. 高亮显示
一般查询出来的效果都要高亮显示的,例如百度里查出来的结果都会标红啥的,Lucene中也可以这么干。首先要引入高亮显示的jar包。
<!-- lucene高亮显示 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>5.3.1</version>
</dependency>
然后要在上面搜索的Java代码中添加以下高亮显示的部分。
public class Searcher {
public static void search(String indexDir, String q) throws Exception {
//省略……
System.out.println("匹配" + q + "共耗时" + (endTime-startTime) + "毫秒");
System.out.println("查询到" + docs.totalHits + "条记录");
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<b><font color=red>","</font></b>"); //如果不指定参数的话,默认是加粗,即<b><b/>
QueryScorer scorer = new QueryScorer(query);//计算得分,会初始化一个查询结果最高的得分
Fragmenter fragmenter = new SimpleSpanFragmenter(scorer); //根据这个得分计算出一个片段
Highlighter highlighter = new Highlighter(simpleHTMLFormatter, scorer);
highlighter.setTextFragmenter(fragmenter); //设置一下要显示的片段
for(ScoreDoc scoreDoc : docs.scoreDocs) { //取出每条查询结果
Document doc = searcher.doc(scoreDoc.doc); //scoreDoc.doc相当于docID,根据这个docID来获取文档
System.out.println(doc.get("city"));
System.out.println(doc.get("desc"));
String desc = doc.get("desc");
//显示高亮
if(desc != null) {
TokenStream tokenStream = analyzer.tokenStream("desc", new StringReader(desc));
String summary = highlighter.getBestFragment(tokenStream, desc);
System.out.println(summary);
}
}
reader.close();
}
public static void main(String[] args) {
String indexDir = "D:\\lucene2";
String q = "上海繁华"; //查询这个字符
try {
search(indexDir, q);
} catch (Exception e) {
e.printStackTrace();
}
}
}
看一下查询结果: 这是浏览器结果
匹配上海繁华共耗时15毫秒
查询到1条记录
上海
上海是个繁华的城市。
上海是个繁华的城市。
console里面是
匹配上海繁华共耗时15毫秒
查询到1条记录
上海
上海是个繁华的城市
<font color="red">上海</font>是个<font color="red">繁华</font>的城市
这里简单解释一下上面程序中的那个得分,也就是说,在一段文本中,可能搜出来有关键字的地方不止一处,所以Lucene会自动计算每一处的得分,也就是最接近用户搜索,然后显示该位置附近的一些片段。上面的例子中描述部分太少了,就一句话,体现不出来,我把对南京的描述加长一点,如下:
南京是一个文化的城市南京,简称宁,是江苏省会,地处中国东部地区,长江下游,濒江近海。全市下辖11个区,总面积6597平方公里,2013年建成区面积752.83平方公里,常住人口818.78万,其中城镇人口659.1万人。[1-4] “江南佳丽地,金陵帝王州”,南京拥有着6000多年文明史、近2600年建城史和近500年的建都史,是中国四大古都之一,有“六朝古都”、“十朝都会”之称,是中华文明的重要发祥地,历史上曾数次庇佑华夏之正朔,长期是中国南方的政治、经济、文化中心,拥有厚重的文化底蕴和丰富的历史遗存。[5-7] 南京是国家重要的科教中心,自古以来就是一座崇文重教的城市,有“天下文枢”、“东南第一学”的美誉。截至2013年,南京有高等院校75所,其中211高校8所,仅次于北京上海;国家重点实验室25所、国家重点学科169个、两院院士83人,均居中国第三。[8-10] 。
这下够长了,如果我搜索“南京文化”,看一下结果:
南京是一个文化的城市南京,简称宁,是江苏省会,地处中国东部地区,长江下游,濒江近海。全市下辖11个区,总面积6597平方公里,2013年建成区面积752.83平方公里,常住人口818.78万,其中
如果我搜索“南京文明”,再看一下结果:
城镇人口659.1万人。[1-4] “江南佳丽地,金陵帝王州”,南京拥有着6000多年文明史、近2600年建城史和近500年的建都史,是中国四大古都之一,有“六朝古都”、“十朝都会”之称,是中华文明的
这就是Lucene中所谓的得分,其实也就是最匹配的片段。可以看出,Lucene的中文检索也是很强大的,当然咯,如果是专业搞搜索的,那还得好好研究研究,一般开发中站内搜索已经够使用了。
【Lucene】Apache Lucene全文检索引擎架构之中文分词和高亮显示4的更多相关文章
- Lucene作为一个全文检索引擎
Lucene作为一个全文检索引擎,其具有如下突出的优点: (1)索引文件格式独立于应用平台.Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件. ...
- 【Lucene】Apache Lucene全文检索引擎架构之入门实战1
Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟的 ...
- 【Lucene】Apache Lucene全文检索引擎架构之构建索引2
上一篇博文中已经对全文检索有了一定的了解,这篇文章主要来总结一下全文检索的第一步:构建索引.其实上一篇博文中的示例程序已经对构建索引写了一段程序了,而且那个程序还是挺完善的.不过从知识点的完整性来考虑 ...
- Lucene基础(三)-- 中文分词及高亮显示
Lucene分词器及高亮 分词器 在lucene中我们按照分词方式把文档进行索引,不同的分词器索引的效果不太一样,之前的例子使用的都是标准分词器,对于英文的效果很好,但是中文分词效果就不怎么样,他会按 ...
- Lucene索引库维护、搜索、中文分词器
删除索引(文档) 需求 某些图书不再出版销售了,我们需要从索引库中移除该图书. 1 @Test 2 public void deleteIndex() throws Exception { 3 // ...
- lucene之中文分词及其高亮显示(五)
中文分词:即换个分词器 Analyzer analyzer = new StandardAnalyzer();// 标准分词器 换成 SmartChineseAnalyzer analyze ...
- 全文检索Solr集成HanLP中文分词
以前发布过HanLP的Lucene插件,后来很多人跟我说其实Solr更流行(反正我是觉得既然Solr是Lucene的子项目,那么稍微改改配置就能支持Solr),于是就抽空做了个Solr插件出来,开源在 ...
- 全文检索Solr集成HanLP中文分词【转】
以前发布过HanLP的Lucene插件,后来很多人跟我说其实Solr更流行(反正我是觉得既然Solr是Lucene的子项目,那么稍微改改配置就能支持Solr),于是就抽空做了个Solr插件出来,开源在 ...
- 【Lucene】Apache Lucene全文检索引擎架构之搜索功能3
上一节主要总结了一下Lucene是如何构建索引的,这一节简单总结一下Lucene中的搜索功能.主要分为几个部分,对特定项的搜索:查询表达式QueryParser的使用:指定数字范围内搜索:指定字符串开 ...
随机推荐
- c++类的隐藏,覆盖和重载,using关键字使用
转载一篇文章: http://www.cnblogs.com/ustc11wj/archive/2012/08/11/2637316.html 类的隐藏和重载不一样 类的隐藏是指 一个类继承自另外一个 ...
- git 本地与远程关联流程
git init git add -A git commit -m '提交' git remote add origin git@github.com:laniu/liuna.git git push ...
- Javascript短路表达式
短路表达式:作为"&&"和"||"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短 ...
- (6)C#项目结构
一.项目下Properites文件夹 Properties文件夹 定义你程序集的属性 项目属性文件夹 一般只有一个 AssemblyInfo.cs 类文件,用于保存程序集的信息,如名称,版本等,这些信 ...
- (4)PHP基本语法、变量、数据类型、运算符、流程控制
一.基本语法 1.PHP在网页里的结构 <?php ..... ?> 2.php的另一种格式(不推荐使用) <script language="php"> ...
- elasticsearch REST api
elasticsearch REST api========================================命令模式:<REST Verb> /<Index>/ ...
- 固件分析工具Binwalk
固件分析工具Binwalk 固件是保存在嵌入式设备存储器的程序.它负责设备运行和功能,如路由器等设备.通过分析固件文件,可以了解设备的工作方式,并且确认是否存在漏洞.Binwalk是Kali Li ...
- 前端中 width 的获取
这篇文章其实是在了解 viewport 的过程中发现这些概念容易混淆做了个小小的总结.viewport的首要关键是宽度的获取,宽度的计算有下面几个属性和方法: clientWidth offsetWi ...
- POJ 3368 Frequent values(线段树区间合并)
[题目链接] http://poj.org/problem?id=3368 [题目大意] 有一个有序序列,要求区间查询出现次数最多的数 [题解] 维护每个区间左端点和右端点,以及左右的长度,还有区间的 ...
- XTU | 人工智能入门复习总结
写在前面 本文严禁转载,只限于学习交流. 课件分享在这里了. 还有人工智能标准化白皮书(2018版)也一并分享了. 绪论 人工智能的定义与发展 定义 一般解释:人工智能就是用 人工的方法在 **机器( ...