lucene

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對象
}
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章