【转载】Lucene学习笔记(二)

来源:互联网 发布:淘宝上有卖A片吗 编辑:程序博客网 时间:2024/06/06 03:14
二、第一个"搜索引擎":
大纲:1.Lucene下载包结构简介
2.使用Lucene为本地文件建立索引
3.测试性搜索
4.改进的意见

1.初识Lucene

1.1 Lucene的下载:可到Apache官网http://lucene.apache.org下载Lucene开发工具包,这里我们用1.4.3稳定版本

1.2 Lucene的源码包结构:

1.2.1 analysis包:该包下的源码类主要用于对需要建立索引的文件内容进行分词、过滤等操作。
除了标准的由JavaCC生成的分词器源代码外,该包中还包含了对德语和俄语分词器与过滤器的支持,ru包是俄语支持包,de包是德语支持包。

1.2.2 standard包:是Lucene的标准分词器包,同时还保留了使用JavaCC生成分词器时的.jj脚本(关于JavaCC的相关内容后面章节会介绍)

1.2.3 document包:主要用于向Lucene提供对Document和Field操作的支持。(Document和Field后面章节会涉及)

1.2.4 index包:是Lucene最重要的一个包,用于向Lucene提供建立索引时各种操作的支持。

1.2.5 queryParser包:用于向Lucene提供检索时的分析支持。搜索引擎除了要在建立索引的时候对大量文本进行分析外,
还要对用户输入的查询关键字进行分析,以便建立Lucene中正确的搜索条件(分析处理用户输入的关键字,
和要搜索的索引中的某个字段(就是Document中的Field的key))进行绑定,解析出一个Query条件对象,

1.2.6 search包: 负责检索的类包,调用该包下的相应的类方法,就可以完成搜索并返回结果集。

1.2.7 store包:主要用于提供对索引存储的支持。它里面的FSDirectory和RAMDirectory类是Lucene中最为常用的两个索引目录,
后面会有对这两个类的讲解。

1.2.8 util包:为Lucene提供了一些工具类和常量类的支持。

2.为本机的文件创建索引:因为要应用所以要创建一个工程,使用Lucene的基本功能,我们只需想工程的lib中导入lucene.jar包即可!

2.1 首先选择用于创建索引的本地文件:"C://lucene_source"中有a.txt、b.txt、c.txt、d.txt文件,
内容都很简单:中华人民共和国、人民共和国、人民、共和国

2.2 指定存放索引文件的目录:"C://lucene_index"

2.3 建立索引:具体代码后边会讲解------------下边"**注意"中是对分词器分词功能的说明,还提供了中文分词的解决方案!!
public class CreateLuceneIndex {
//定义一个索引写入器
private IndexWriter indexWriter;
//缺省构造方法*/
public CreateLuceneIndex() {
/*
初始化写入器,指定保存索引的目录,指定一个标准的分词器 true代表每次都要保存最新的索引信息到指定的目录,如果已经存在那么先删除

**注意:标准的分词器对中文的支持并不是很好,他只能单个字建立索引,例如:"中华人民共和国"这段话,
会被分成"中"、"华"、"人"、"民"、"共"、"和"、"国",而不是我们期望的"中华"、"人民"、"共和国"
还有一种是CJKAnalyzer类(需要单独下载JAR包)是进行二分法分词,对于上面的"中华人民共和国",会被分成"中华"、"华人"、"人民"、"民共"、"共和"、"和国"
还有一种是MMAnalyzer类(需要单独下载JAR包)是词典分词中的极易分词器,将会分成我们期望的"中华"、"人民"、"共和国",对于词典分词还有一种分词器是庖丁分词器(也要单独下载,庖丁分词和极易分词都可以很好的解决中文索引问题)
*/
indexWriter = new IndexWriter(Constants.INDEX_DESC_PATH, new StandardAnalyzer(), true);
}
//将指定的要建立索引的文件包装成Document对象 然后返回包装好的Document对象
public Document getDocument(File file) {
// 创建一个预接收数据的Document对象
Document document = new Document();
// 创建一个Read读取文件的流对象
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
/*
* 将文件中的内容保存到Field对象,因为Field对象是一个键值对,所以要指定一个Key键 Field.Text("content",
* bufferedReader)方法是建立Field对象而且创建索引,但是不存储索引(由API得知)
*/
document.add(Field.Text("content", bufferedReader));
//得到文件的绝对路径
document.add(Field.Keyword("path", file.getAbsolutePath()));
//返回封装好的Document对像
return document;
}
//核心方法:为指定目录的文档建立索引,然后将索引写入到磁盘
public void writerToIndex() {
// 关联到C://lucene_source目录
File file = new File("C://lucene_source");
// 因为file对象此时代表的是一个目录
if (file.isDirectory()) {
// 得到目录中的所有文件名(包含扩展名)
String[] fileNames = file.list();
for (int i = 0; i < fileNames.length; i++) {
File source = new File(file, fileNames[i]);
// 将文件转换成Document对象
Document document = getDocument(source);
System.out.println("正在为文件 " + fileNames[i] + " 建立索引...");
indexWriter.addDocument(document);
}
}
}
//关闭写入器
public void close(){
//关闭写入器,最后将索引写入磁盘
}
//主方法入口点
public static void main(String[] args) {
// 创建一个实例对象:目的是可以调用构造方法和调用类内的相应方法
CreateLuceneIndex createLuceneIndex = new CreateLuceneIndex();
//创建索引开始时间
Date start = new Date();
//写入索引到磁盘
createLuceneIndex.writerToIndex();
//创建索引结束时间
Date end = new Date();
System.out.println("建立索引耗时: " + (end.getTime() - start.getTime()) + "毫秒!");
//关闭索引写入器
createLuceneIndex.close();
}
}

2.4 开始搜索:具体代码后边会讲解
public class SearchMachine {
// 创佳搜索器对象
private IndexSearcher indexSearcher;
// 创建Lucene格式的查询条件对象
private Query query;

//缺省构造方法
public SearchMachine() {
// 初始化搜索器:并指定保存索引的目录
indexSearcher = new IndexSearcher(Constants.INDEX_DESC_PATH);
}
//根据指定的用户输入的查询关键字查询结果
public Hits getSearchResults(String queryKey) {
//定义接收结果的Hits对象
Hits hits = null;
//根据查询关键字、字段名称、分词器,解析关键字,并封装成Lucene格式的对对应字段(content)的查询条件
query = QueryParser.parse(queryKey, "content", new StandardAnalyzer());
//搜索开始时间
Date start = new Date();
//开始搜索
hits = indexSearcher.search(query);
//搜索结束时间
Date end = new Date();
System.out.println("搜索完成,用时: " + (end.getTime() - start.getTime()) + "毫秒!");
//返回结果
return hits;
}
//打印结果集
public void printSearchResults(Hits hits){
//判断是否结果为空
if(hits.length() == 0){
System.out.println("对不起,没有找到您想要的搜索结果!");
return;
}
//循环输出检索结果的每个Document对象中包装的内容
for (int i = 0; i < hits.length(); i++) {
//得到结果集中的Document对象
Document document = hits.doc(i);
System.out.println("这是第 " + (i+1) + "个被检索到的文件,文件名为: " + document.get("path"));
}
}
//搜索功能的入口
public static void main(String[] args) {
//创建对象:目的是调用构造方法,和可以调用本类中的其他方法
SearchMachine searchMachine = new SearchMachine();
//用"中华"作为用户输入的搜索关键字进行查找,打印结果
searchMachine.printSearchResults(searchMachine.getSearchResults("中华"));
System.out.println("-------------------------------------------------");
//用"人民"作为用户输入的搜索关键字进行查找,打印结果
searchMachine.printSearchResults(searchMachine.getSearchResults("人民"));
System.out.println("-------------------------------------------------");
//用"共和国"作为用户输入的搜索关键字进行查找,打印结果
searchMachine.printSearchResults(searchMachine.getSearchResults("共和国"));
System.out.println("-------------------------------------------------");
}
}
原创粉丝点击