ReganHoo 2011-06-03
Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。其功能非常的强大,api也很简单。总得来说用Lucene来进行搜索和操作数据库是差不多的(有点像),Document可以看作是数据库的一行记录,Field可以看作是数据库的字段。用lucene实现搜索引擎就像用JDBC实现连接数据库一样简单。
1.到apache官网上下载目前的最新版本lucene-3.1.0,下载地址:http://www.apache.org/dyn/closer.cgi/lucene/java/
2.将lucene-core-3.1.0.jar包导到MyEclipse或Eclipse
3.在D:\test\luceneTest\docs目录下,随便建四个txt文件作测试数据源,随便起名啦,就1.txt,2.txt,3.txt,4.txt,内容依次如下:
[华人民共和国]
[有限公司]
[学习中]
[中国历史]
[美丽中国]
4.建立索引
package test.lucene; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Date; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.SimpleFSDirectory; import org.apache.lucene.util.Version; public class TextFileIndexer { public static void main(String[] args) throws Exception { // 保存索引文件的地方 String indexDir = "D:\\test\\luceneTest\\index"; // 将要搜索TXT文件的地方 String dateDir = "D:\\test\\luceneTest\\docs"; // 创建Directory对象 Directory dir = new SimpleFSDirectory(new File(indexDir)); Analyzer luceneAnalyzer = new StandardAnalyzer(Version.LUCENE_31); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_31, luceneAnalyzer); IndexWriter indexWriter = new IndexWriter(dir, config); File[] textFiles = new File(dateDir).listFiles(); // 增加document到索引去 for (int i = 0; i < textFiles.length; i++) { System.out.println("File " + textFiles[i].getCanonicalPath() + " 正在被索引."); String temp = FileReaderAll(textFiles[i].getCanonicalPath(), "GBK"); System.out.println(temp); Document document = new Document(); Field FieldPath = new Field("path", textFiles[i].getPath(), Field.Store.YES, Field.Index.NO); Field FieldBody = new Field("body", temp, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); document.add(FieldPath); document.add(FieldBody); indexWriter.addDocument(document); } // optimize()方法是对索引进行优化 indexWriter.optimize(); indexWriter.close(); System.out.println("numDocs:"+indexWriter.numDocs()); } public static String FileReaderAll(String FileName, String charset) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream( FileName), charset)); String line = new String(); String temp = new String(); while ((line = reader.readLine()) != null) { temp += line; } reader.close(); return temp; } }
索引的结果:
FileD:\test\luceneTest\docs\1.txt正在被索引.
华人民共和国
FileD:\test\luceneTest\docs\2.txt正在被索引.
有限公司
FileD:\test\luceneTest\docs\3.txt正在被索引.
学习中
FileD:\test\luceneTest\docs\4.txt正在被索引.
中国历史美丽中国
numDocs:4
5.建立好索引后就是查询
package test.lucene; import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.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.store.Directory; import org.apache.lucene.store.SimpleFSDirectory; import org.apache.lucene.util.Version; public class TestQuery { public static void main(String[] args) throws IOException, ParseException { //保存索引文件的地方 String indexDir = "D:\\test\\luceneTest\\index"; Directory dir = new SimpleFSDirectory(new File(indexDir)); //创建 IndexSearcher对象,相比IndexWriter对象,这个参数就要提供一个索引的目录就行了 IndexSearcher indexSearch = new IndexSearcher(dir); //创建QueryParser对象,第一个参数表示Lucene的版本,第二个表示搜索Field的字段,第三个表示搜索使用分词器 QueryParser queryParser = new QueryParser(Version.LUCENE_31, "body", new StandardAnalyzer(Version.LUCENE_31)); //生成Query对象 Query query = queryParser.parse("中国"); //搜索结果 TopDocs里面有scoreDocs[]数组,里面保存着索引值 TopDocs hits = indexSearch.search(query, 10); //hits.totalHits表示一共搜到多少个 System.out.println("找到了"+hits.totalHits+"个"); //循环hits.scoreDocs数据,并使用indexSearch.doc方法把Document还原,再拿出对应的字段的值 for (int i = 0; i < hits.scoreDocs.length; i++) { ScoreDoc sdoc = hits.scoreDocs[i]; Document doc = indexSearch.doc(sdoc.doc); System.out.println(doc.get("path")); } indexSearch.close(); } }
其运行结果:
找到了3个
D:\test\luceneTest\docs\4.txt
D:\test\luceneTest\docs\3.txt
D:\test\luceneTest\docs\1.txt
注:可以看出结果并不好,因为我要查的是"中国",结果1.txt和3.txt也被列出来了,只因为其中含有其中一个字,网上查了一下,说StandardAnalyzer是可以用于中文分词,但它是一元分词,机械地将一个汉字做为一个词元来切分的,后面有时间看一下中文分词器
补充说明:Lucene其实很简单的,它最主要就是做两件事:建立索引和进行搜索
来看一些在lucene中使用的术语,这里并不打算作详细的介绍,只是点一下而已----因为这一个世界有一种好东西,叫搜索。
IndexWriter:lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。
Analyzer:分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。
Directory:索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。
Document:文档;Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。
Field:字段。
IndexSearcher:是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具;
Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。
QueryParser:是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。
Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene中,搜索的结果的集合是用Hits类的实例来表示的。
参考资料:
1.http://www.blogjava.net/liuwentao253/archive/2007/01/08/92401.html
2.http://lucene-group.group.iteye.com/group/wiki
3.http://www.chedong.com/tech/lucene.html