最近在学luncene全文检索。跟着学习视频学的,推荐www.java1234.com上去学下。
关于全文检索:推荐看下全文检索的原理。这里我就不再写了,下面把利用中文分词检索查询的demo给贴出来,以供以后使用。
首先是pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.luncene.demo</groupId>
<artifactId>LunceneDemo</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>LunceneDemo Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- lucnene核心包 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.5.0</version>
</dependency>
<!-- lucnene解析包 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>5.5.0</version>
</dependency>
<!-- lucene 公共包分析器 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>5.5.0</version>
</dependency>
<!-- 中文分词 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>5.5.0</version>
</dependency>
<!-- 关键词高亮显示 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>LunceneDemo</finalName>
</build>
</project>
Indexer.java
package com.java1234.luncene06;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import java.nio.file.Paths;
/**创建中文索引
* Created by T430 on 2017/8/2.
*/
public class Indexer {
private Integer ids[]={1,2,3};
private String citys[]={"青岛","南京","上海"};
private String descs[]={
"青岛是一个美丽的城市",
"南京是一个文化的城市南京,简称宁,是江苏省会,地处中国东部地区,长江下游,濒江近海。全市下辖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] 。\",\n",
"上海是一个金融城市"
};
private Directory dir;//字典
/**
* 获取inderWriter示例
* @return
* @throws Exception
*/
private IndexWriter getWriter() throws Exception{
// Analyzer analyzer =new StandardAnalyzer();//标准分词器
//中文分词器
SmartChineseAnalyzer analyzer= new SmartChineseAnalyzer();
IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
IndexWriter writer=new IndexWriter(dir,iwc);//把分的词和字典都写入进去
return writer;
}
/**
* 构造器
* @param indexDir 保存的地址
* @throws Exception
*/
private 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();//这里选用的是luncene的document,别选错了哦
/**
* 这个是把ID加进去,因为ID是int类型的,所以需要用到的是IntField,由于占的空间不大,所以选择YES保存进去
*/
doc.add(new IntField("id",ids[i], Field.Store.YES));
/**
* 这个是把String类型的保存进去,算是标签吧(个人理解),所占空间不大,所以也选择YES保存进去
*/
doc.add(new StringField("city",citys[i],Field.Store.YES));
/**
* 这个是把内容保存进去,大字段的所以选择的是TextField
*/
doc.add(new TextField("desc",descs[i],Field.Store.YES));
//添加文档
writer.addDocument(doc);
}
writer.close();//写完以后就要关闭流,保证性能
}
public static void main(String[] args) {
try {
new Indexer().index("E:\\lucene6");
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面就开始创建检索的类
package com.java1234.luncene06;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import java.io.StringReader;
import java.nio.file.Paths;
/**中文分词查询及高亮显示
* Created by T430 on 2017/8/2.
*/
public class Seracher {
/**
* 查询
* @param indexDir 索引路径
* @param q 查询用的关键词
* @throws Exception
*/
public static void search(String indexDir, String q) throws Exception{
Directory dir= FSDirectory.open(Paths.get(indexDir));//获取字典内容
IndexReader reader = DirectoryReader.open(dir);//读出字典
//索引查询器
IndexSearcher is= new IndexSearcher(reader);
// Analyzer analyzer =new StandardAnalyzer();//标准分词器
SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer();//中文分词器
//查询解析
QueryParser parser= new QueryParser("desc",analyzer);
//格式化查询
Query query=parser.parse(q);
//查询前的时间
long start= System.currentTimeMillis();
//查询,返回前十的文档
TopDocs hits=is.search(query,10);
//查询后的时间
long end=System.currentTimeMillis();
System.out.println("匹配:"+q+",中共花费了:"+(end-start
)+"毫秒");
QueryScorer scorer= new QueryScorer(query);//片段得分,计算得分,把得分高的片段计算出来
Fragmenter fragmenter= new SimpleSpanFragmenter(scorer);//把得分放进去,进行格式化
//设置成html的格式,默认的是粗体, 咱们可以给他改成粗体,红色
SimpleHTMLFormatter simpleHTMLFormatter= new SimpleHTMLFormatter("<b><font color='red'>","</font></b>");
Highlighter highlighter=new Highlighter(simpleHTMLFormatter,scorer);//高亮显示片段得分高的部分
highlighter.setTextFragmenter(fragmenter);//把得分的摘要设置成text显示出来
//查询到的文档
for (ScoreDoc scoreDoc: hits.scoreDocs){
//根据主键ID获取文档
Document doc= is.doc(scoreDoc.doc);
System.out.println(doc.get("city"));//输出城市
String desc=doc.get("desc");//完整的desc数据
System.out.println(desc);//输出完整的desc
/**
* 如果查询得到的desc不为空,则进行高亮,片段显示
*/
if (desc!=null){
//获取很多的片段
TokenStream tokenStream= analyzer.tokenStream("desc",new StringReader(desc));
String ZhaiYao= highlighter.getBestFragment(tokenStream,desc);//把权重高的片段摘要显示出来
System.out.println("显示高亮的关键词片段:===》"+ZhaiYao);
}
}
reader.close();//关闭
}
public static void main(String[] args) {
String indexDir = "E:\\lucene6";//索引目录
String q="南京 厚重";//关键词
try {
search(indexDir,q);
} catch (Exception e) {
e.printStackTrace();
}
}
}
到此为止。 一个简单的中文全文检索就做好了。 对于一般的搜索来说, 完全够用了。 大家可以对这个再进行封装。 就到这了。