lucene
全文檢索
Lucene實現全文檢索的流程
創建索引
查詢索引
配置開發環境
創建索引庫
查詢索引庫
分析器的分析過程
測試分析器的分詞效果
第三方中文分析器
索引庫的維護
添加文檔
刪除文檔
修改文檔
Lucene的高級查詢Lucene的查詢
使用Query的子類查詢
MatchAllDocsQuery
TermQuery
NumericRangeQuery
BooleanQuery
使用QueryParser
QueryParser
MulitFieldQueryParser
MAVEN 導入 jar包
<!--核心包 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>5.3.1</version> </dependency> <!--一般分詞器,適用於英文分詞 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> <version>5.3.1</version> </dependency> <!--中文分詞器 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-smartcn</artifactId> <version>5.3.1</version> </dependency> <!--對分詞索引查詢解析 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> <version>5.3.1</version> </dependency> <!--檢索關鍵字高亮顯示 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>5.3.1</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
創建索引庫
使用indexwriter對象創建索引
創建一個java工程,並導入jar包。
創建一個indexwriter對象。
指定索引庫的存放位置Directory對象
指定一個分析器,對文檔內容進行分析。
創建document對象。
創建field對象,將field添加到document對象中。
使用indexwriter對象將document對象寫入索引庫,此過程進行索引創建。並將索引和document對象寫入索引庫。
關閉IndexWriter對象。
package com.stevezong.lucene; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.FileUtils; 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.Field.Store; import org.apache.lucene.document.LongField; import org.apache.lucene.document.StoredField; 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; public class LuceneTest { public static void main(String[] args) throws Exception { //指定索引庫的存放位置Directory對象 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); //指定一個分析器,對文檔內容進行分析。 Analyzer analyzer = new StandardAnalyzer(); // 配置對象 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); //創建一個indexwriter對象。 IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); //創建field對象,將field添加到document對象中。 File file = new File("F:\\5DWIFI最新字典\\新字典"); File[] files =file.listFiles(); for (File subFile : files) { //文件名 String fileName = subFile.getName(); //文件大小 long fileSize = FileUtils.sizeOf(subFile); //文件路徑 String filePath = subFile.getAbsolutePath(); //文件內容 String fileContent = FileUtils.readFileToString(subFile); //創建文件名域 //第一個參數:域的名稱 //第二個參數:域的內容 //第三個參數:是否存儲 //文件名域 Field fileNameField = new TextField("fileName", fileName, Store.YES); //文件內容域 Field fileContentField = new TextField("fileContent", fileContent, Store.YES); //文件路徑域 Field filePathField = new StoredField("filePath", filePath); //文件大小域 Field fileSizeField = new LongField("fileSize", fileSize, Store.YES); //1.3創建document對象。 Document document = new Document(); document.add(fileSizeField); document.add(filePathField); document.add(fileContentField); document.add(fileNameField); //使用indexwriter對象將document對象寫入索引庫,此過程進行索引創建。並將索引和document對象寫入索引庫。 indexWriter.addDocument(document); } indexWriter.close(); //關閉IndexWriter對象。 } }
Field類 (4類)
=======================================================================================================================================================
StringField(FieldName, FieldValue,Store.YES))
數據類型:字符串
Analyzed是否分析:N
Indexed 是否索引:Y
Stored 是否存儲:Y或N
說明:這個Field用來構建一個字符串Field,但是不會進行分析,會將整個串存儲在索引中,比如(訂單號,姓名等)是否存儲在文檔中用Store.YES或Store.NO決定
*********************************************************************************************************************************************************
LongField(FieldName, FieldValue,Store.YES)
數據類型:Long型
Analyzed是否分析:Y
Indexed 是否索引:Y
Stored 是否存儲:Y或N
說明:這個Field用來構建一個Long數字型Field,進行分析和索引,比如(價格)是否存儲在文檔中用Store.YES或Store.NO決定
*********************************************************************************************************************************************************
StoredField(FieldName, FieldValue)
數據類型:重載方法,支持多種類型
Analyzed是否分析:N
Indexed 是否索引:N
Stored 是否存儲:Y
說明:這個Field用來構建不同類型Field不分析,不索引,但要Field存儲在文檔中
*********************************************************************************************************************************************************
TextField(FieldName, FieldValue, Store.NO)或TextField(FieldName, reader)
數據類型:字符串或流
Analyzed是否分析:Y
Indexed 是否索引:Y
Stored 是否存儲:Y或N
說明:如果是一個Reader, lucene猜測內容比較多,會採用Unstored的策略.
=======================================================================================================================================================
使用 對應版本的luke 就可讀取
https://github.com/DmitryKey/luke/releases?after=luke-5.2.0
查詢索引庫
1:創建一個Directory對象,也就是索引庫存放的位置。
2:創建一個indexReader對象,需要指定Directory對象。
3:創建一個indexsearcher對象,需要指定IndexReader對象
4:創建一個TermQuery對象,指定查詢的域和查詢的關鍵詞。
5:執行查詢。
6:回查詢結果。遍歷查詢結果並輸出。
7:關閉IndexReader對象
package com.stevezong.lucene; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; public class LuceneTest2 { public static void main(String[] args) throws Exception { //1:創建一個Directory對象,也就是索引庫存放的位置。 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); //2:創建一個indexReader對象,需要指定Directory對象。 IndexReader indexReader = DirectoryReader.open(directory); //3:創建一個indexsearcher對象,需要指定IndexReader對象 IndexSearcher indexSearcher = new IndexSearcher(indexReader); //4:創建一個TermQuery對象,指定查詢的域和查詢的關鍵詞。 Term term = new Term("fileName","2015"); Query query = new TermQuery(term); //5:執行查詢。 TopDocs topDocs = indexSearcher.search(query, 2); //6:回查詢結果。遍歷查詢結果並輸出。 ScoreDoc[] scoreDocs = topDocs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) { int doc = scoreDoc.doc; Document document = indexSearcher.doc(doc); String fileName = document.get("fileName"); String fileContent = document.get("fileContent"); String filePath = document.get("filePath"); String fileSize = document.get("fileSize"); System.out.println(fileName+":"+filePath+":"+fileSize+":"+fileContent); } indexReader.close(); //7:關閉IndexReader對象 } }
indexSearcher.search(query, n)根據Query搜索,返回評分最高的n條記錄
indexSearcher.search(query, filter, n)根據Query搜索,添加過濾策略,返回評分最高的n條記錄
indexSearcher.search(query, n, sort)根據Query搜索,添加排序策略,返回評分最高的n條記錄
indexSearcher.search(booleanQuery, filter, n, sort)根據Query搜索,添加過濾策略,添加排序策略,返回評分最高的n條記錄
Lucene自帶中文分詞器
StandardAnalyzer:
單字分詞:就是按照中文一個字一個字地進行分詞。如:“我愛中國”,
效果:“我”、“愛”、“中”、“國”。
CJKAnalyzer
二分法分詞:按兩個字進行切分。如:“我是中國人”,效果:“我是”、“是中”、“中國”“國人”。
上邊兩個分詞器無法滿足需求。
SmartChineseAnalyzer
對中文支持較好,但擴展性差,擴展詞庫,禁用詞庫和同義詞庫等不好處理
package com.stevezong.lucene; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; 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.Store; import org.apache.lucene.document.TextField; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.Term; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.NumericRangeQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.junit.Test; public class LuceneTest3 { @Test // 全刪 public void testDel() throws Exception { // 1.2.1)指定索引庫的存放位置Directory對象 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); // 1.2.2)指定一個分析器,對文檔內容進行分析。 Analyzer analyzer = new StandardAnalyzer(); // 1.2.3) 配置對象 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); // 1.2創建一個indexwriter對象。 IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); // 全刪 indexWriter.deleteAll(); indexWriter.close(); } @Test // 條件刪 public void testDelBySome() throws Exception { // 1.2.1)指定索引庫的存放位置Directory對象 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); // 1.2.2)指定一個分析器,對文檔內容進行分析。 Analyzer analyzer = new StandardAnalyzer(); // 1.2.3) 配置對象 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); // 1.2創建一個indexwriter對象。 IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); // 創建刪除條件 Term term = new Term("fileName", "2015"); Query query = new TermQuery(term); // 條件刪 indexWriter.deleteDocuments(query); indexWriter.close(); } @Test // 修改 public void testUpdate() throws Exception { // 1.2.1)指定索引庫的存放位置Directory對象 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); // 1.2.2)指定一個分析器,對文檔內容進行分析。 Analyzer analyzer = new StandardAnalyzer(); // 1.2.3) 配置對象 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); // 1.2創建一個indexwriter對象。 Document doc = new Document(); TextField fileNameField = new TextField("fileName", "測試修改功能文件名", Store.YES); TextField fileContentField = new TextField("fileContent", "測試修改功能文件內容", Store.YES); doc.add(fileNameField); doc.add(fileContentField); IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); indexWriter.updateDocument(new Term("fileName", "50"), doc); indexWriter.close(); } @Test // 查詢所有 public void testSelectAll() throws Exception { // 1:創建一個Directory對象,也就是索引庫存放的位置。 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); // 2:創建一個indexReader對象,需要指定Directory對象。 IndexReader indexReader = DirectoryReader.open(directory); // 3:創建一個indexsearcher對象,需要指定IndexReader對象 IndexSearcher indexSearcher = new IndexSearcher(indexReader); //實現類換了 Query query = new MatchAllDocsQuery(); TopDocs docs = indexSearcher.search(query, 20); ScoreDoc[] scoreDocs = docs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) { int doc = scoreDoc.doc; Document document = indexSearcher.doc(doc); String fileName = document.get("fileName"); String fileContent = document.get("fileContent"); String filePath = document.get("filePath"); String fileSize = document.get("fileSize"); System.out.println(fileName+":"+filePath+":"+fileSize); } indexReader.close(); //7:關閉IndexReader對象 } @Test // 查詢 根據數值範圍查詢 public void testSelectByFileSize() throws Exception { // 1:創建一個Directory對象,也就是索引庫存放的位置。 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); // 2:創建一個indexReader對象,需要指定Directory對象。 IndexReader indexReader = DirectoryReader.open(directory); // 3:創建一個indexsearcher對象,需要指定IndexReader對象 IndexSearcher indexSearcher = new IndexSearcher(indexReader); //實現類換了 Query query = NumericRangeQuery.newLongRange("fileSize", 0L, 500L, true, true); TopDocs docs = indexSearcher.search(query, 20); ScoreDoc[] scoreDocs = docs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) { int doc = scoreDoc.doc; Document document = indexSearcher.doc(doc); String fileName = document.get("fileName"); String fileContent = document.get("fileContent"); String filePath = document.get("filePath"); String fileSize = document.get("fileSize"); System.out.println(fileName+":"+filePath+":"+fileSize); } indexReader.close(); //7:關閉IndexReader對象 } @Test // 查詢 組合查詢 public void testSelectBooleanQuery() throws Exception { // 1:創建一個Directory對象,也就是索引庫存放的位置。 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); // 2:創建一個indexReader對象,需要指定Directory對象。 IndexReader indexReader = DirectoryReader.open(directory); // 3:創建一個indexsearcher對象,需要指定IndexReader對象 IndexSearcher indexSearcher = new IndexSearcher(indexReader); //實現類換了 BooleanQuery booleanQuery =new BooleanQuery(); //條件1 Query query = NumericRangeQuery.newLongRange("fileSize", 0L, 500L, true, true); //條件2 Query fileNameQuery = new TermQuery( new Term("fileName","2015")); //將 兩個條件 添加到 對象中 並設定 連接條件 必須 不必須 可能 過濾 booleanQuery.add(query,Occur.MUST); booleanQuery.add(fileNameQuery,Occur.SHOULD); TopDocs docs = indexSearcher.search(booleanQuery, 20); ScoreDoc[] scoreDocs = docs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) { int doc = scoreDoc.doc; Document document = indexSearcher.doc(doc); String fileName = document.get("fileName"); String fileContent = document.get("fileContent"); String filePath = document.get("filePath"); String fileSize = document.get("fileSize"); System.out.println(fileName+":"+filePath+":"+fileSize); } indexReader.close(); //7:關閉IndexReader對象 } @Test //條件解析的對象查詢 //需要導包 public void testQueryParser() throws Exception { // 1:創建一個Directory對象,也就是索引庫存放的位置。 Path path = Paths.get("d:\\szTemp"); Directory directory = FSDirectory.open(path); // 2:創建一個indexReader對象,需要指定Directory對象。 IndexReader indexReader = DirectoryReader.open(directory); // 3:創建一個indexsearcher對象,需要指定IndexReader對象 IndexSearcher indexSearcher = new IndexSearcher(indexReader); //實現類換了默認域分詞器 QueryParser queryParser =new QueryParser("fileName",new StandardAnalyzer()); //查詢所有 域:值 //Query query = queryParser.parse("*:*"); //fileName:2015 //Query query = queryParser.parse("2015"); //fileContent:cheese //Query query = queryParser.parse("fileContent:cheese"); // cheese is a java 88888888 經過分詞器 後再去查找 Query query = queryParser.parse("fileContent:cheese is a java 88888888"); TopDocs docs = indexSearcher.search(query, 20); ScoreDoc[] scoreDocs = docs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) { int doc = scoreDoc.doc; Document document = indexSearcher.doc(doc); String fileName = document.get("fileName"); String fileContent = document.get("fileContent"); String filePath = document.get("filePath"); String fileSize = document.get("fileSize"); System.out.println(fileName+":"+filePath+":"+fileSize); } indexReader.close(); //7:關閉IndexReader對象 } }