lucene

lucene
全文檢索java

二、Lucene實現全文檢索的流程
a) 建立索引
b) 查詢索引
三、配置開發環境
四、建立索引庫
五、查詢索引庫
六、分析器的分析過程
a) 測試分析器的分詞效果
b) 第三方中文分析器
七、索引庫的維護
a) 添加文檔
b) 刪除文檔
c) 修改文檔
八、Lucene的高級查詢Lucene的查詢
a) 使用Query的子類查詢
i. MatchAllDocsQuery
ii. TermQuery
iii. NumericRangeQuery
iv. BooleanQuery
b) 使用QueryParser
i. QueryParser
ii. MulitFieldQueryParsergit

 

MAVEN 導入 jar包github

<!--核心包 -->
<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>

 

建立索引庫

1使用indexwriter對象建立索引apache

1.1 建立一個java工程,並導入jar包。
1.2建立一個indexwriter對象。
1.2.1)指定索引庫的存放位置Directory對象
1.2.2)指定一個分析器,對文檔內容進行分析。
1.3建立document對象。
1.4建立field對象,將field添加到document對象中。
1.5使用indexwriter對象將document對象寫入索引庫,此過程進行索引建立。並將索引和document對象寫入索引庫。
1.6關閉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 {
        // 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);
        // 1.4建立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);
            // 1.5使用indexwriter對象將document對象寫入索引庫,此過程進行索引建立。並將索引和document對象寫入索引庫。
            indexWriter.addDocument(document);
        }
        indexWriter.close();
        // 1.6關閉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對象spa

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
對中文支持較好,但擴展性差,擴展詞庫,禁用詞庫和同義詞庫等很差處理code

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

}
相關文章
相關標籤/搜索