傳統檢索:文件 → 內容。倒排索引:詞項 → 包含該詞的文檔列表。Lucene 核心數據結構即倒排索引,實現毫秒級全文檢索。
Store.YES(存儲原值)、Store.NO(不存儲)、Index.ANALYZED(分詞索引)、Index.NOT_ANALYZED(不分詞索引)。StandardAnalyzer 標準分詞(按語法、標點切分)。<dependencies> <dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>4.9.1</version></dependency> <dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>4.9.1</version></dependency> <dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>4.9.1</version></dependency> <dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queries</artifactId><version>4.9.1</version></dependency> <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency> </dependencies>
public class MyIndexFiles {
// 索引目錄
private static final String INDEX_DIR = "D:\\documents\\Lucene\\MyDemo\\index";
// 文檔源目錄
private static final String DOCS_DIR = "D:\\documents\\Lucene\\MyDemo\\docs";
public static void main(String[] args) throws IOException {
// 1. 打開索引目錄
FSDirectory directory = FSDirectory.open(new File(INDEX_DIR));
// 2. 分詞器
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_4_9);
// 3. 索引寫配置
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_9, analyzer);
// 4. 創建 IndexWriter
IndexWriter writer = new IndexWriter(directory, config);
// 5. 遍歷文檔構建索引
File[] files = new File(DOCS_DIR).listFiles();
for (File file : files) {
Document doc = new Document();
String filename = file.getName();
long modified = file.lastModified();
String content = FileUtils.readFileToString(file); // commons-io
// filename: 不分詞、存儲(用於展示)
doc.add(new StringField("filename", filename, Field.Store.YES));
// modify: 長整型、存儲
doc.add(new LongField("modify", modified, Field.Store.YES));
// contents: 分詞索引、不存儲(節省空間,檢索用)
doc.add(new TextField("contents", content, Field.Store.NO));
// 更新模式:同名文件覆蓋
writer.updateDocument(new Term("filename", filename), doc);
}
writer.close();
System.out.println("索引構建完成");
}
@Test
public void search() throws IOException, ParseException {
// 1. 打開索引
Directory directory = FSDirectory.open(new File(INDEX_DIR));
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
// 2. 構建查詢:針對 contents 域搜 "111"
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_4_9);
QueryParser parser = new QueryParser(Version.LUCENE_4_9, "contents", analyzer);
Query query = parser.parse("111");
// 3. 執行搜索,取前 6 條
TopDocs topDocs = searcher.search(query, 6);
ScoreDoc[] hits = topDocs.scoreDocs;
// 4. 遍歷結果
for (ScoreDoc hit : hits) {
Document doc = searcher.doc(hit.doc);
System.out.println("文件名: " + doc.get("filename"));
System.out.println("修改時間: " + doc.get("modify"));
// contents 未存儲,此處為 null;實際可通過 filename 讀取原文件高亮片段
System.out.println("內容片段: " + doc.get("contents"));
}
reader.close();
}
}
StringField:不分詞,整體作為一個 Term,適合 ID、路徑、枚舉值精確匹配。TextField:分詞索引,適合長文本全文檢索。Field.Store.NO:不存儲原值,僅建立索引,節省磁盤;檢索時需通過存儲字段(如 filename/路徑)回溯原文件獲取片段。updateDocument(term, doc):先刪除匹配 term 的文檔,再添加新文檔,實現「增量更新/去重」。QueryParser:支持豐富查詢語法(通配符、範圍、布爾組合),生產環境建議直接構建 Query 對象避免解析開銷。SearcherManager + ReferenceManager 實現秒級可見。Highlighter + FastVectorHighlighter。