Lucene介绍:
Lucene是一个高性能,可伸缩的全文检索工具包,可以使用他为你的应用程序添加索引和搜索能力。(注:它不是一个完整的搜索应用程序),Lucene目前是我们熟知的Apache里的一个开发项目,也是目前最为流行的基于Java开源全文检索工具包。
官网:http://lucene.apache.org/,从官网上看可以发现其版本不止Java的还有.NET等等。
目前已经有很多应用程序的搜索功能是基于Lucene的,例如我们用的Eclipse在第一次使用的时候,会有一个进度条,那就是创建索引的过程,方便Eclipse 的帮助系统的搜索功能。Lucene能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化为文本的,Lucene就能对你的文档进行索引和搜索。比如你要对一些HTML文档、PDF文档进行索引的话你就首先需要把HTML文档和PDF文档转换为文本格式的,然后将转换后的内容交给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对象。
TopDocs:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。
Ok,废话就这么多,直接上代码。
FirstLucene
1、添加jar包
lucene-core-3.5.0.jar(核心)
lucene-analyzers-3.5.0.jar(分词器)
lucene-highlighter-3.5.0.jar(高亮器)
2、建立索引
3、 搜索
FirstLucene.java:
- packagecom.iflytek.lucene;
- importjava.io.File;
- importorg.apache.lucene.analysis.Analyzer;
- importorg.apache.lucene.analysis.standard.StandardAnalyzer;
- importorg.apache.lucene.document.Document;
- importorg.apache.lucene.index.IndexReader;
- importorg.apache.lucene.index.IndexWriter;
- importorg.apache.lucene.index.IndexWriterConfig;
- importorg.apache.lucene.queryParser.MultiFieldQueryParser;
- importorg.apache.lucene.queryParser.QueryParser;
- importorg.apache.lucene.search.Filter;
- importorg.apache.lucene.search.IndexSearcher;
- importorg.apache.lucene.search.Query;
- importorg.apache.lucene.search.ScoreDoc;
- importorg.apache.lucene.search.TopDocs;
- importorg.apache.lucene.store.Directory;
- importorg.apache.lucene.store.FSDirectory;
- importorg.apache.lucene.util.Version;
- /**
- *@authorxudongwang2012-2-2
- *
- *Email:[email protected]
- */
- publicclassFirstLucene{
- /**
- *源文件路径
- */
- privateStringfilePath01="F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene01.txt";
- privateStringfilePath02="F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene02.txt";
- privateStringfilePath03="F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene03.txt";
- /**
- *索引路径
- */
- privateStringindexPath="F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneIndex";
- /**
- *分词器,这里我们使用默认的分词器,标准分析器(好几个,但对中文的支持都不好)
- */
- privateAnalyzeranalyzer=newStandardAnalyzer(Version.LUCENE_35);
- /**
- *创建索引
- *
- *@throwsException
- */
- publicvoidcreateIndex()throwsException{
- Documentdocument01=File2Document.file2Document(filePath01);//要进行索引的单元
- Documentdocument02=File2Document.file2Document(filePath02);
- Documentdocument03=File2Document.file2Document(filePath03);
- //将Document添加到索引库中
- FileindexFile=newFile(indexPath);
- Directorydirectory=FSDirectory.open(indexFile);
- //IndexWriter是用来操作(增、删、改)索引库的
- //true,表示每次都创建新的,有了就删掉再创建
- IndexWriterConfigconf=newIndexWriterConfig(Version.LUCENE_35,
- analyzer);
- IndexWriterindexWriter=newIndexWriter(directory,conf);
- indexWriter.addDocument(document01);
- indexWriter.addDocument(document02);
- indexWriter.addDocument(document03);
- indexWriter.close();//涉及到资源的都需要释放
- }
- /**
- *搜索
- *
- *@paramqueryStr
- *搜索的关键词
- *@throwsException
- */
- publicvoidsearch(StringqueryStr)throwsException{
- //1、把要搜索的文本解析为Query对象
- //指定在哪些字段查询
- String[]fields={"name","content"};
- //QueryParser:是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。
- QueryParserqueryParser=newMultiFieldQueryParser(Version.LUCENE_35,
- fields,analyzer);
- //Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。
- Queryquery=queryParser.parse(queryStr);
- //2、进行查询
- FileindexFile=newFile(indexPath);
- //IndexSearcher是用来在索引库中进行查询的
- //IndexSearcherindexSearcher=new
- //IndexSearcher(FSDirectory.open(indexFile));
- Directorydirectory=FSDirectory.open(indexFile);
- IndexReaderindexReader=IndexReader.open(directory);
- IndexSearcherindexSearcher=newIndexSearcher(indexReader);
- //Filter过滤器,我们可以将查出来的结果进行过滤,可以屏蔽掉一些不想给用户看到的内容
- Filterfilter=null;
- //10000表示一次性在数据库中查询多少个文档
- //topDocs类似集合
- TopDocstopDocs=indexSearcher.search(query,filter,10000);
- System.out.println("总共有【"+topDocs.totalHits+"】条匹配的结果");//注意这里的匹配结果是指文档的个数,而不是文档中包含搜索结果的个数
- //3、打印结果
- for(ScoreDocscoreDoc:topDocs.scoreDocs){
- intdocSn=scoreDoc.doc;//文档内部编号
- Documentdocument=indexSearcher.doc(docSn);//根据文档编号取出相应的文档
- File2Document.printDocumentInfo(document);//打印出文档信息
- }
- }
- publicstaticvoidmain(String[]args)throwsException{
- FirstLucenelucene=newFirstLucene();
- //lucene.createIndex();
- lucene.search("other");
- System.out.println("---------------------------");
- lucene.search("iteye");
- System.out.println("---------------------------");
- lucene.search("too");
- System.out.println("---------------------------");
- }
- }
package com.iflytek.lucene;import java.io.File;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.queryParser.MultiFieldQueryParser;import org.apache.lucene.queryParser.QueryParser;import org.apache.lucene.search.Filter;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.FSDirectory;import org.apache.lucene.util.Version;/** * @author xudongwang 2012-2-2 * * Email:[email protected] */public class FirstLucene { /** * 源文件路径 */ private String filePath01 = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene01.txt"; private String filePath02 = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene02.txt"; private String filePath03 = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene03.txt"; /** * 索引路径 */ private String indexPath = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneIndex"; /** * 分词器,这里我们使用默认的分词器,标准分析器(好几个,但对中文的支持都不好) */ private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35); /** * 创建索引 * * @throws Exception */ public void createIndex() throws Exception { Document document01 = File2Document.file2Document(filePath01);// 要进行索引的单元 Document document02 = File2Document.file2Document(filePath02); Document document03 = File2Document.file2Document(filePath03); // 将Document添加到索引库中 File indexFile = new File(indexPath); Directory directory = FSDirectory.open(indexFile); // IndexWriter是用来操作(增、删、改)索引库的 // true,表示每次都创建新的,有了就删掉再创建 IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_35, analyzer); IndexWriter indexWriter = new IndexWriter(directory, conf); indexWriter.addDocument(document01); indexWriter.addDocument(document02); indexWriter.addDocument(document03); indexWriter.close();// 涉及到资源的都需要释放 } /** * 搜索 * * @param queryStr * 搜索的关键词 * @throws Exception */ public void search(String queryStr) throws Exception { // 1、把要搜索的文本解析为Query对象 // 指定在哪些字段查询 String[] fields = { "name", "content" }; // QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。 QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_35, fields, analyzer); // Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。 Query query = queryParser.parse(queryStr); // 2、进行查询 File indexFile = new File(indexPath); // IndexSearcher 是用来在索引库中进行查询的 // IndexSearcher indexSearcher = new // IndexSearcher(FSDirectory.open(indexFile)); Directory directory = FSDirectory.open(indexFile); IndexReader indexReader = IndexReader.open(directory); IndexSearcher indexSearcher = new IndexSearcher(indexReader); // Filter 过滤器,我们可以将查出来的结果进行过滤,可以屏蔽掉一些不想给用户看到的内容 Filter filter = null; // 10000表示一次性在数据库中查询多少个文档 // topDocs 类似集合 TopDocs topDocs = indexSearcher.search(query, filter, 10000); System.out.println("总共有【" + topDocs.totalHits + "】条匹配的结果");// 注意这里的匹配结果是指文档的个数,而不是文档中包含搜索结果的个数 // 3、打印结果 for (ScoreDoc scoreDoc : topDocs.scoreDocs) { int docSn = scoreDoc.doc;// 文档内部编号 Document document = indexSearcher.doc(docSn);// 根据文档编号取出相应的文档 File2Document.printDocumentInfo(document);// 打印出文档信息 } } public static void main(String[] args) throws Exception { FirstLucene lucene = new FirstLucene(); //lucene.createIndex(); lucene.search("other"); System.out.println("---------------------------"); lucene.search("iteye"); System.out.println("---------------------------"); lucene.search("too"); System.out.println("---------------------------"); }}
File2Document.java:
- packagecom.iflytek.lucene;
- importjava.io.BufferedReader;
- importjava.io.File;
- importjava.io.FileInputStream;
- importjava.io.FileNotFoundException;
- importjava.io.IOException;
- importjava.io.InputStreamReader;
- importorg.apache.lucene.document.Document;
- importorg.apache.lucene.document.Field;
- importorg.apache.lucene.document.Field.Index;
- importorg.apache.lucene.document.Field.Store;
- /**
- *@authorxudongwang2012-2-2
- *
- *Email:[email protected]
- */
- publicclassFile2Document{
- /**
- *File--->Document
- *
- *@paramfilePath
- *File路径
- *
- *@returnDocument对象
- */
- publicstaticDocumentfile2Document(StringfilePath){
- //文件要存放:name,content,size,path
- Filefile=newFile(filePath);
- Documentdocument=newDocument();
- //Store.YES是否存储yesnocompress(压缩之后再存)
- //Index是否进行索引Index.ANALYZED分词后进行索引,NOT_ANALYZED不索引,NOT_ANALYZED
- //不分词直接索引
- document.add(newField("name",file.getName(),Store.YES,
- Index.ANALYZED));
- document.add(newField("content",readFileContent(file),Store.YES,
- Index.ANALYZED));
- document.add(newField("size",String.valueOf(file.length()),
- Store.YES,Index.NOT_ANALYZED));//不分词,但是有时需要索引,文件大小(int)转换成String
- document.add(newField("path",file.getAbsolutePath(),Store.YES,
- Index.NOT_ANALYZED));//不需要根据文件的路径来查询
- returndocument;
- }
- /**
- *读取文件内容
- *
- *@paramfile
- *File对象
- *@returnFile的内容
- */
- privatestaticStringreadFileContent(Filefile){
- try{
- BufferedReaderreader=newBufferedReader(newInputStreamReader(
- newFileInputStream(file)));
- StringBuffercontent=newStringBuffer();
- try{
- for(Stringline=null;(line=reader.readLine())!=null;){
- content.append(line).append("\n");
- }
- }catch(IOExceptione){
- e.printStackTrace();
- }
- returncontent.toString();
- }catch(FileNotFoundExceptione){
- e.printStackTrace();
- }
- returnnull;
- }
- /**
- *<pre>
- *获取name属性值的两种方法
- *1.Filedfield=document.getFiled("name");
- *field.stringValue();
- *2.document.get("name");
- *</pre>
- *
- *@paramdocument
- */
- publicstaticvoidprintDocumentInfo(Documentdocument){
- //TODOAuto-generatedmethodstub
- System.out.println("name-->"+document.get("name"));
- System.out.println("content-->"+document.get("content"));
- System.out.println("path-->"+document.get("path"));
- System.out.println("size-->"+document.get("size"));
- }
- }
package com.iflytek.lucene;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStreamReader;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.document.Field.Index;import org.apache.lucene.document.Field.Store;/** * @author xudongwang 2012-2-2 * * Email:[email protected] */public class File2Document { /** * File--->Document * * @param filePath * File路径 * * @return Document对象 */ public static Document file2Document(String filePath) { // 文件要存放:name,content,size,path File file = new File(filePath); Document document = new Document(); // Store.YES 是否存储 yes no compress(压缩之后再存) // Index 是否进行索引 Index.ANALYZED 分词后进行索引,NOT_ANALYZED 不索引,NOT_ANALYZED // 不分词直接索引 document.add(new Field("name", file.getName(), Store.YES, Index.ANALYZED)); document.add(new Field("content", readFileContent(file), Store.YES, Index.ANALYZED)); document.add(new Field("size", String.valueOf(file.length()), Store.YES, Index.NOT_ANALYZED));// 不分词,但是有时需要索引,文件大小(int)转换成String document.add(new Field("path", file.getAbsolutePath(), Store.YES, Index.NOT_ANALYZED));// 不需要根据文件的路径来查询 return document; } /** * 读取文件内容 * * @param file * File对象 * @return File的内容 */ private static String readFileContent(File file) { try { BufferedReader reader = new BufferedReader(new InputStreamReader( new FileInputStream(file))); StringBuffer content = new StringBuffer(); try { for (String line = null; (line = reader.readLine()) != null;) { content.append(line).append("\n"); } } catch (IOException e) { e.printStackTrace(); } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } /** * <pre> * 获取name属性值的两种方法 * 1.Filed field = document.getFiled("name"); * field.stringValue(); * 2.document.get("name"); * </pre> * * @param document */ public static void printDocumentInfo(Document document) { // TODO Auto-generated method stub System.out.println("name -->" + document.get("name")); System.out.println("content -->" + document.get("content")); System.out.println("path -->" + document.get("path")); System.out.println("size -->" + document.get("size")); }}
HelloLucene01.txt:
|
Hello, my name is wang xudong, I in iteye blog address is xdwangiflytek.iteye.com. |
HelloLucene02.txt:
|
Hello, my name is wang xudong, I in iteye blog address is xdwangiflytek.iteye.com too. |
HelloLucene03.txt:
|
iteye too other. |
创建的目录结构为:
运行结果: