lucene是一种基于索引的搜索技术。它是一个高性能、可伸缩的信息搜索库。它使你可以为你的应用程序添加索引和搜索能力。它可以索引并能使得可以转换成[color=red]文本格式[/color]的任何数据能够被搜索。它并不关心数据的来源、格式甚至它的语言,只要你能将它转换为文本。这就意味着你可经索引并搜索存放于文件中的数据:在远程服务器上的web页面,存于本地文件系统的文档,简单的文本文件,微软Word文档,HTML或PDF文件或任何其它能够提取出文本信息的格式。同样,利用Lucene你可以索引存放于数据库中的数据,提供给用户很多数据库没有提供的
全文搜索的能力。
如果要使用lucene必须导入它相关的jar文件,具体在哪儿下我就不说了,自己去摆渡一下。
[size=large]Lucene 软件包分析[/size]
Lucene 软件包的发布形式是一个 JAR 文件,下面我们分析一下这个 JAR 文件里面的主要的 JAVA 包,使读者对之有个初步的了解。
Package: org.apache.lucene.document
这个包提供了一些为封装要索引的文档所需要的类,比如 Document, Field。这样,每一个文档最终被封装成了一个 Document 对象。
Package: org.apache.lucene.analysis
这个包主要功能是对文档进行分词,因为文档在建立索引之前必须要进行分词,所以这个包的作用可以看成是为建立索引做准备工作。
Package: org.apache.lucene.index
这个包提供了一些类来协助创建索引以及对创建好的索引进行更新。这里面有两个基础的类:IndexWriter 和 IndexReader,其中 IndexWriter 是用来创建索引并添加文档到索引中的,IndexReader 是用来删除索引中的文档的。
Package: org.apache.lucene.search
这个包提供了对在建立好的索引上进行搜索所需要的类。比如 IndexSearcher 和 Hits, IndexSearcher 定义了在指定的索引上进行搜索的方法,Hits 用来保存搜索得到的结果。
1.首先建立一个项目,并导入lucene的相关jar文件
[quote]
LUCENE_HOME/lucene-1.4-final.jar
[/quote]
2.建立索引
在执行搜索之前我们必须为要被搜索的文件创建索引,当然这个类还提供了删除索引的方法。
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:
Document
Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。
Field
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。
Analyzer
在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。
IndexWriter
IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。
Directory
这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。
因此先建立一个创建索引的类:Indexer.java
问题:如何更新索引中的文档。Lucene中并没有提供更新方法。Document必须首先从索引中删除然后再重新添加它。
3.运行Indexer.java的main方法,控制台会列出所有符合条件的被索引的文件
4.搜索文档
创建好索引之后,我们就可以在索引中进行搜索了。
利用Lucene进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某个关键词或短语的文档。Lucene提供了几个基础的类来完成这个过程,它们分别是呢IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。
Query
这是一个抽象类,他有多个实现,比如TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成Lucene能够识别的Query。
Term
Term是搜索的基本单位,一个Term对象有两个String类型的域组成。生成一个Term对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个Field上进行查找,第二个参数代表了要查询的关键词。
TermQuery
TermQuery是抽象类Query的一个子类,它同时也是Lucene支持的最为基本的一个查询类。生成一个TermQuery对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个Term对象。
IndexSearcher
IndexSearcher是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个IndexSearcher的实例在一个索引上进行操作。
Hits
Hits是用来保存搜索的结果的。
因此需要建立一个搜索的类:Searcher.java
5.运行Searcher.java会在控制台上看到所有包含六位的文件名称。
当然你也可以使用更多复杂的查询,例如“六位 离开家”,中间有一个空格,这表示所有包含“六位”或者“离开家”的文件。
“六位 AND 离开家”表示包含“六位”且包含“离开家”的文件。
全文搜索的能力。
如果要使用lucene必须导入它相关的jar文件,具体在哪儿下我就不说了,自己去摆渡一下。
[size=large]Lucene 软件包分析[/size]
Lucene 软件包的发布形式是一个 JAR 文件,下面我们分析一下这个 JAR 文件里面的主要的 JAVA 包,使读者对之有个初步的了解。
Package: org.apache.lucene.document
这个包提供了一些为封装要索引的文档所需要的类,比如 Document, Field。这样,每一个文档最终被封装成了一个 Document 对象。
Package: org.apache.lucene.analysis
这个包主要功能是对文档进行分词,因为文档在建立索引之前必须要进行分词,所以这个包的作用可以看成是为建立索引做准备工作。
Package: org.apache.lucene.index
这个包提供了一些类来协助创建索引以及对创建好的索引进行更新。这里面有两个基础的类:IndexWriter 和 IndexReader,其中 IndexWriter 是用来创建索引并添加文档到索引中的,IndexReader 是用来删除索引中的文档的。
Package: org.apache.lucene.search
这个包提供了对在建立好的索引上进行搜索所需要的类。比如 IndexSearcher 和 Hits, IndexSearcher 定义了在指定的索引上进行搜索的方法,Hits 用来保存搜索得到的结果。
1.首先建立一个项目,并导入lucene的相关jar文件
[quote]
LUCENE_HOME/lucene-1.4-final.jar
[/quote]
2.建立索引
在执行搜索之前我们必须为要被搜索的文件创建索引,当然这个类还提供了删除索引的方法。
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:
Document
Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。
Field
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。
Analyzer
在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。
IndexWriter
IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。
Directory
这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。
因此先建立一个创建索引的类:Indexer.java
package com.zzg.index;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
public class Indexer {
public static void main(String[] args) throws Exception {
String indexPath = "C:\\Users\\toshiba\\index";
String dataPath = "C:\\Users\\toshiba\\data";
File indexDir = new File(indexPath);
File dataDir = new File(dataPath);
long start = new Date().getTime();
int numIndexed = indexDirectory(indexDir, dataDir);
long end = new Date().getTime();
System.out.println("indexing" + numIndexed + "files took"
+ (end - start) + "milliseconds");
//documentDelete(indexDir,1);
}
/**
* 使用递归遍历出被搜索目录里的所有文件
*
* @param indexDir
* 索引目录
* @param dataDir
* 被索引目录
* @return
* @throws Exception
*/
private static int indexDirectory(File indexDir, File dataDir)
throws Exception {
if (!dataDir.exists() || !dataDir.isDirectory()) {
throw new Exception(dataDir
+ "dose no exist or is not is directory");
}
IndexWriter writer = new IndexWriter(indexDir, new StandardAnalyzer(),
true);
writer.setUseCompoundFile(false);
indexDirectory(writer, dataDir);
int numIndexed = writer.docCount();
writer.optimize();
writer.close();
return numIndexed;
}
/**
* 把被索引目录中包含已txt为后缀的文件创建索引
* @param writer
* @param dir
* @throws Exception
*/
private static void indexDirectory(IndexWriter writer, File dir)
throws Exception {
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (f.isDirectory()) {
indexDirectory(writer, f);
} else if (f.getName().endsWith(".txt")) {
indexFile(writer, f);
}
}
}
/**
* 创建索引
* @param writer
* @param f
* @throws Exception
*/
private static void indexFile(IndexWriter writer, File f) throws Exception {
if (f.isHidden() || !f.exists() || !f.canRead()) {
return;
}
System.out.println("Indexing" + f.getCanonicalPath());
Document doc = new Document();
doc.add(Field.Text("contents", new FileReader(f)));
doc.add(Field.Keyword("filename", f.getCanonicalPath()));
writer.addDocument(doc);
}
/**
* 根据内部文档号删除Document
* @param indexDir
* @param docNum
* @throws IOException
*/
private static void documentDelete(File indexDir,int docNum) throws IOException{
Directory dir=FSDirectory.getDirectory(indexDir, false);
IndexReader reader=IndexReader.open(dir);
//返回下一个可用的内部Document号
System.out.println("maxDoc="+reader.maxDoc());
//返回索引中的Document的数目
System.out.println("numDoc="+reader.numDocs());
//删除号码为docNum的Document
reader.delete(docNum);
//检查指定编号的Document的状态
System.out.println(reader.isDeleted(docNum));
//检查打开索引是否包含删除标志的Document
System.out.println(reader.hasDeletions());
System.out.println(reader.maxDoc());
//当调用close方法时才真正被删除
reader.close();
//重新打开IndexReader
reader=IndexReader.open(dir);
System.out.println(reader.maxDoc());
System.out.println(reader.numDocs());
reader.close();
}
}
问题:如何更新索引中的文档。Lucene中并没有提供更新方法。Document必须首先从索引中删除然后再重新添加它。
3.运行Indexer.java的main方法,控制台会列出所有符合条件的被索引的文件
4.搜索文档
创建好索引之后,我们就可以在索引中进行搜索了。
利用Lucene进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某个关键词或短语的文档。Lucene提供了几个基础的类来完成这个过程,它们分别是呢IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。
Query
这是一个抽象类,他有多个实现,比如TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成Lucene能够识别的Query。
Term
Term是搜索的基本单位,一个Term对象有两个String类型的域组成。生成一个Term对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个Field上进行查找,第二个参数代表了要查询的关键词。
TermQuery
TermQuery是抽象类Query的一个子类,它同时也是Lucene支持的最为基本的一个查询类。生成一个TermQuery对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个Term对象。
IndexSearcher
IndexSearcher是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个IndexSearcher的实例在一个索引上进行操作。
Hits
Hits是用来保存搜索的结果的。
因此需要建立一个搜索的类:Searcher.java
package com.zzg.index;
import java.io.File;
import java.util.Date;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
public class Searcher {
public static void main(String[] args) throws Exception {
File indexDir = new File("C:\\Users\\toshiba\\index");
String q = "六位";
if (!indexDir.exists() || !indexDir.isDirectory()) {
throw new Exception(indexDir
+ "dose not exist or is not a directory");
}
search(indexDir, q);
}
private static void search(File indexDir, String q) throws Exception {
Directory fsDir = FSDirectory.getDirectory(indexDir, false);
// 打开索引
IndexSearcher is = new IndexSearcher(fsDir);
// 分析查询
Query query = QueryParser.parse(q, "contents", new StandardAnalyzer());
long start = new Date().getTime();
// 搜索索引
Hits hits = is.search(query);
long end = new Date().getTime();
System.err.println("Found" + hits.length() + "document(s) (in"
+ (end - start) + "milliseconds) that matched query'" + q
+ "':");
for (int i = 0; i < hits.length(); i++) {
// 得到匹配的文档
Document doc = hits.doc(i);
System.out.println(doc.get("filename"));
}
}
}
5.运行Searcher.java会在控制台上看到所有包含六位的文件名称。
当然你也可以使用更多复杂的查询,例如“六位 离开家”,中间有一个空格,这表示所有包含“六位”或者“离开家”的文件。
“六位 AND 离开家”表示包含“六位”且包含“离开家”的文件。