Apache Lucene的一個簡單示例
阿新 • • 發佈:2019-01-03
Lucene是apache軟體基金會jakarta專案組的一個子專案,是一個開放原始碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文字分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟體開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎。Lucene是一套用於全文檢索和搜尋的開源程式庫,由Apache軟體基金會支援和提供。Lucene提供了一個簡單卻強大的應用程式介面,能夠做全文索引和搜尋。在Java開發環境裡Lucene是一個成熟的免費開源工具。就其本身而言,Lucene是當前以及最近幾年最受歡迎的免費Java資訊檢索程式庫。人們經常提到資訊檢索程式庫,雖然與搜尋引擎有關,但不應該將資訊檢索程式庫與搜尋引擎相混淆。
**
一個簡單的例子
**
1、引入Maven依賴
JDK版本:1.8.0_181
Lucene版本:4.0.0
POI版本:3.17,可處理2016之後的Word和Excel
最新版本可到此查詢mvnrepository
<properties>
<lucene.version>4.0.0</lucene.version>
<poi.version>3.17</poi.version>
</properties>
<dependencies>
<!--Lucene 核心包 START -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lucene.version}</version>
</dependency>
<!--一般分詞器,適用於英文分詞-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lucene.version}</version>
</dependency>
<!--中文分詞器-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>${lucene.version}</version>
</dependency>
<!--對分詞索引查詢解析-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>${lucene.version}</version>
</dependency>
<!--檢索關鍵字高亮顯示-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>${lucene.version}</version>
</dependency>
<!--Lucene 核心包 END -->
<!-- Excel和Word文件處理依賴 START -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8</version>
</dependency>
<!-- Excel和Word文件處理依賴 END -->
</dependencies>
2、建立需要檢索的檔案
在資料夾D:\luceneData\下手動建立1.txt,2.docx,3.xlsx三個檔案,裡面含有“中國”兩個漢字的文字內容。
3、建立檔案目錄索引
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.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
public class CreateLuceneIndex {
private final static Logger log = LoggerFactory.getLogger(CreateLuceneIndex.class);
private static String content = "";// 檔案裡的內容
private static String INDEX_DIR = "D:\\luceneIndex";// 存放索引的位置
private static String DATA_DIR = "D:\\luceneData";// 存放檔案的位置
private static Analyzer analyzer = null;
private static Directory directory = null;
private static IndexWriter indexWriter = null;
/**
* 建立當前檔案目錄的索引
*
* @param path 當前檔案目錄
* @return 是否成功
*/
public static boolean createIndex(String path) {
Date date1 = new Date();
File indexFile = new File(INDEX_DIR);
if (!indexFile.exists()) {
indexFile.mkdirs();
}
List<File> fileList = getFileList(path);
for (File file : fileList) {
content = "";
// 獲取檔案字尾
String type = file.getName().substring(file.getName().lastIndexOf(".") + 1);
if ("txt".equalsIgnoreCase(type)) {
content += txt2String(file);
} else if ("doc".equalsIgnoreCase(type) || "docx".equalsIgnoreCase(type)) {
content += doc2String(file);
} else if ("xls".equalsIgnoreCase(type) || "xlsx".equalsIgnoreCase(type)) {
content += xls2String(file);
}
System.out.println("name :" + file.getName());
System.out.println("path :" + file.getPath());
System.out.println("content :" + content);
System.out.println("=======================");
try {
analyzer = new StandardAnalyzer(Version.LUCENE_40);// 使用中文分詞器
directory = FSDirectory.open(new File(INDEX_DIR));
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);
indexWriter = new IndexWriter(directory, config);
Document document = new Document();
document.add(new TextField("filename", file.getName(), Field.Store.YES));
document.add(new TextField("content", content, Field.Store.YES));
document.add(new TextField("path", file.getPath(), Field.Store.YES));
indexWriter.addDocument(document);// 新增文件
indexWriter.commit();
closeWriter();// close了才真正寫到文件中
} catch (Exception e) {
log.error("建立檔案目錄索引異常:" + e.getMessage(), e);
return false;
}
}
Date date2 = new Date();
System.out.println("建立索引-----耗時:" + (date2.getTime() - date1.getTime()) + "ms");
return true;
}
/**
* 過濾目錄下的檔案
*
* @param dirPath 想要獲取檔案的目錄
* @return 返回檔案list
*/
private static List<File> getFileList(String dirPath) {
File[] files = new File(dirPath).listFiles();
List<File> fileList = new ArrayList<File>();
for (File file : files) {
if (isTxtFile(file.getName())) {
fileList.add(file);
}
}
return fileList;
}
/**
* 讀取txt檔案的內容
*
* @param file 想要讀取的檔案物件
* @return 返回檔案內容
*/
private static String txt2String(File file) {
String result = "";
try {
// 構造一個BufferedReader類來讀取檔案(解決中文亂碼問題)
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"));
String s = null;
// 使用readLine方法,一次讀一行
while ((s = br.readLine()) != null) {
result += s;
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 讀取doc檔案內容
*
* @param file 想要讀取的檔案物件
* @return 返回檔案內容
*/
public static String doc2String(File file) {
String result = "";
if (file.exists() && file.isFile()) {
InputStream is = null;
HWPFDocument doc = null;
XWPFDocument docx = null;
POIXMLTextExtractor extractor = null;
try {
FileInputStream fis = new FileInputStream(file);
// 判斷word的兩種格式doc,docx
if (file.getPath().toLowerCase().endsWith("doc")) {
doc = new HWPFDocument(fis);
// 文件文字內容
result = doc.getDocumentText();
} else if (file.getPath().toLowerCase().endsWith("docx")) {
docx = new XWPFDocument(fis);
extractor = new XWPFWordExtractor(docx);
// 文件文字內容
result = extractor.getText();
} else {
log.error("不是word文件:" + file.getPath());
}
} catch (Exception e) {
log.error("word檔案讀取異常:" + e.getMessage(), e);
} finally {
try {
if (doc != null) {
doc.close();
}
if (extractor != null) {
extractor.close();
}
if (docx != null) {
docx.close();
}
if (is != null) {
is.close();
}
} catch (Exception e) {
log.error("關閉IO異常:" + e.getMessage(), e);
}
}
}
return result;
}
/**
* 讀取xls檔案內容
*
* @param file 想要讀取的檔案物件
* @return 返回檔案內容
*/
public static String xls2String(File file) {
String result = "";
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
Workbook workbook = null;
// 判斷excel的兩種格式xls,xlsx
if (file.getPath().toLowerCase().endsWith("xlsx")) {
workbook = new XSSFWorkbook(fis);
} else if (file.getPath().toLowerCase().endsWith("xls")) {
workbook = new HSSFWorkbook(fis);
}
// 得到sheet的總數
int numberOfSheets = workbook.getNumberOfSheets();
//System.out.println("一共" + numberOfSheets + "個sheet");
// 迴圈每一個sheet
for (int i = 0; i < numberOfSheets; i++) {
//得到第i個sheet
Sheet sheet = workbook.getSheetAt(i);
//System.out.println(sheet.getSheetName() + " sheet");
// 得到行的迭代器
Iterator<Row> rowIterator = sheet.iterator();
int rowCount = 0;
// 迴圈每一行
while (rowIterator.hasNext()) {
//System.out.print("第" + (++rowCount) + "行 ");
// 得到一行物件
Row row = rowIterator.next();
// 得到列物件
Iterator<Cell> cellIterator = row.cellIterator();
int columnCount = 0;
// 迴圈每一列
while (cellIterator.hasNext()) {
//System.out.print("第" + (++columnCount) + "列:");
// 得到單元格物件
Cell cell = cellIterator.next