这里面用的是比较新的Lucene4.10.2 做的一个实例。(lucene的索引不能太大,要不然效率会很低。大于1G的时候就必须考虑分布索引的问题)
先介绍一下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对象。
话说Lucene就两个重要步骤,一个是创建索引,一个是查询索引,首先看下如何创建索引的代码。
import util.IOUtil; /** * @author ${朱良兴} *2015-1-26 */ public class CreateIndexer { public void createIndex() throws Exception{ IOUtil utils= new IOUtil(); // 一、创建索引 // 内存索引模板 Directory dir = new RAMDirectory(); Analyzer analyzer = new StandardAnalyzer(); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_2, analyzer); IndexWriter indexWriter = new IndexWriter(dir, config); //文件位置。 File fileDir = new File( "E:\ftp" ); String path = "E:\ftp"; long startTime = new Date().getTime(); String id; //获取所有的文件名。 List <String> fileList = utils.getFileName(path); for(int i=0; i<fileList.size();i++){ String content = utils.getFileContent(new File(fileList.get(i)), "GBK"); id ="id"+i; indexPost(id, content); } // 测试一下索引的时间 long endTime = new Date().getTime(); System.out .println( " 这花费了 " + (endTime - startTime) + " 毫秒来把文档增加到索引里面去! " + fileDir.getPath()); indexWriter.close(); } @SuppressWarnings("deprecation") private static void indexPost(String id,String content){ /* 这里放索引文件的位置 */ File indexDir = new File("E:\index"); Analyzer analyzer = new IKAnalyzer(); TextField postIdField = new TextField("id", id, Store.YES); // 不要用StringField TextField postContentField = new TextField("content", content, Store.YES); Document doc = new Document(); doc.add(postIdField); doc.add(postContentField); IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_4_10_2, analyzer); iwConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); try { Directory fsDirectory = FSDirectory.open(indexDir); IndexWriter indexWriter = new IndexWriter(fsDirectory, iwConfig); indexWriter.addDocument(doc); indexWriter.close(); } catch (Exception e) { e.printStackTrace(); } }
第二就是查询:
/** * 查询索引 * @author ${朱良兴} *2015-1-26 */ public class DoSearch { public static void main(String[] args) throws Exception { //创建索引 CreateIndexer createIndexer = new CreateIndexer(); createIndexer.createIndex(); Analyzer analyzer = new IKAnalyzer(); File indexDir = new File("E:\index"); try { Directory fsDirectory = FSDirectory.open(indexDir); DirectoryReader ireader = DirectoryReader.open(fsDirectory); IndexSearcher isearcher = new IndexSearcher(ireader); QueryParser qp = new QueryParser("content", analyzer); //使用QueryParser查询分析器构造Query对象 qp.setDefaultOperator(QueryParser.AND_OPERATOR); Query query = qp.parse("么么哒"); // 搜索Lucene long beginTime = new Date().getTime(); TopDocs topDocs = isearcher.search(query , 100); //搜索相似度最高的100条记录 long endTime = new Date().getTime(); System.out.println("命中:" + topDocs.totalHits); System.out.println("搜索花费的时间:"+(endTime-beginTime)+"毫秒"); ScoreDoc[] scoreDocs = topDocs.scoreDocs; for (int i = 0; i < topDocs.totalHits; i++){ Document targetDoc = isearcher.doc(scoreDocs[i].doc); System.out.println("内容:" + targetDoc.toString()); } } catch (Exception e) { } } }
用到的工具类代码:
package util; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; /** * IO 工具类。 * @author ${朱良兴} *2015-1-26 */ public class IOUtil{ List<String> fileList = new ArrayList<String>(); /** * 根据文件的全路径获得所有的文件内容 * @param fileName * @param charset * @return * @throws Exception */ public String getFileContent(File fileName, String charset) throws Exception{ 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; } /** * 获取所有的文件名 * @param path * @return * @throws Exception */ public List<String> getFileName(String path) throws Exception{ String filenName =""; //文件位置。 File fileDir = new File(path); File[] textFiles = fileDir.listFiles(); if (textFiles!=null){ // 增加document到索引去 for ( int i = 0 ; i < textFiles.length; i ++ ) { if (textFiles[i].isFile()) { System.out.println( " File " + textFiles[i].getCanonicalPath() + " 正在被索引. " ); filenName=textFiles[i].getCanonicalPath(); fileList.add(filenName); }else{ getFileName(textFiles[i].getCanonicalPath()); } } } return fileList; } }
这里是和IK Analyzer 结合使用的简单示例