當前位置:
首頁 > 最新 > Lucene基本概念及使用

Lucene基本概念及使用

1. 搜索引擎組件

1.1

索引組件

為了快速搜索大量的文本,必須針對文本建立索引,將文本內容轉換成能夠進行快速搜索的格式。

這個過程就叫做索引操作(indexing),輸出就是索引(index)

1.1.2 建立文檔

獲取原始內容之後,就需要對內容進行索引,首先必須將內容轉換成文檔,以供搜索引擎使用。

文檔主要包括幾個帶值的域,比如標題、正文、摘要、作者和鏈接(URL)。

然後需要將原始內容中的文本提取出來寫入各個文檔。

1.1.3 文檔分析

搜索引擎不能直接對文本進行索引,而必須將文本分割成一系列被稱為 辭彙單元 的獨立原子元素。

這一步驟決定文檔中的文本域如何分割成 辭彙單元 系列。

Lucene 提供了大量內嵌的分析器能夠輕鬆完成這步操作

1.1.4 文檔索引

在本步驟中,文檔將被加入到索引列表。

1.2

搜索組件

搜索處理過程就是從索引中查找單詞,從而找到包含該單詞的文檔。

1.2.1 建立查詢

搜索請求會被轉換成搜索引擎使用的 查詢(query) 對象格式。

查詢對象可能很簡單,也可能很複雜。 Lucene 提供了一個稱之為 查詢解析器(QueryParser) 的強大開發包,用它可以根據通用查詢語法將用戶輸入的文本處理成查詢對象。

查詢語句可以包含 布爾運算、短語查詢或通配符查詢。

1.2.2 搜索查詢

查詢檢索索引並返回與查詢語句匹配的文檔,結果返回時按照查詢請求來排序

常見的搜索理論模型:

1.純布爾模型:文檔不管是否匹配查詢請求,都不會被評分,匹配文檔與評分不相關,一條查詢僅獲取所有匹配文檔集合的一個子集。

2.向量空間模型:查詢語句和文檔都是高維空間的向量模型,這裡每一個獨立的項都是一個維度,查詢語句和文檔之間的相關性或相似性由各個向量之間的距離計算得到。

3.概率模型:採用全概率的方法來計算文檔和查詢語句匹配的概率。

Lucene 採用了 空間向量模型和純布爾模型

2. 核心技術

Lucene 是一個全文搜索框架

● 倒排索引

● 壓縮演算法

● 二元搜索

2.1

倒排索引

● 根據屬性的值來查找記錄,這種索引表中的每一項都包括一個屬性值和具有該屬性值的各記錄的地址。由於不是由記錄來確定屬性,而是由屬性值來確定記錄的位置,因而成為倒排索引。

● 單詞——文檔矩陣

3. Lucene

的工作方法

Lucene 提供的服務實際包含兩部分,一入一出:

入就是寫入,將提供的源(本質上是字元串)寫入索引或者將其從索引中刪除;

出就是讀取,向用戶提供全文搜索服務,讓用戶可以通過關鍵詞定位源。

● 寫入:源字元首先經過 analyzer 處理,包括:分詞,拆分成一個個單詞;去除 stopword 。將源中需要的信息加入 Document 的各個 Field 中,並把需要索引的 Field 索引起來,把需要存儲的 Field 存儲起來。

● 讀取:用戶提供關鍵詞,經過 analyzer 處理,對處理後的關鍵詞搜索索引,找出對應的 Document。用戶根據需要從找到的 Document 中提取出需要的 Field。

document:用戶提供的源是一條條記錄,它們可以是文本文件、字元串或者資料庫表的一條記錄等等。一條記錄經過索引之後,就是以一個 Document 的形式存儲在索引文件中的。用戶進行搜索,也是以 Document 列表的形式返回。

field:一個 Document 可以包含多個信息域,例如一篇文章可以包括標題、正文、最後修改時間等信息域,這些信息域是通過 Field 在 Document 中存儲的。

Field 有兩個屬性可選:存儲和索引。通過存儲屬性,可以控制是否對這個 Field 進行索引。

——張嘉佳《從你的全世界路過》

4. 示例代碼

4.1

4.1 導入依賴

org.apache.lucene

lucene-core

5.5.4

org.apache.lucene

lucene-queries

5.5.4

org.apache.lucene

lucene-queryparser

5.5.4

org.apache.lucene

lucene-analyzers-common

5.5.4

org.apache.lucene

lucene-highlighter

5.5.4

commons-io

commons-io

2.5

commons-lang

commons-lang

2.5

commons-logging

commons-logging

1.2

4.2

環境準備

準備 index 和 data 兩個目錄,分別用於存放索引和文檔

● data 隨便從其他項目中複製了幾個 LICENSE

● index 保持為空,當 Lucene 運行的時候會自動進行創建

4.3

創建索引

public classCreateIndex{

/*

* 索引目錄

*/

public static finalString INDEX_DIR ="/Users/destiny/IdeaProjects/lucene-demo/src/main/resources/index";

/*

* 文本目錄

*/

public static finalString DATA_DIR ="/Users/destiny/IdeaProjects/lucene-demo/src/main/resources/data";

public voidcreateIndex() throwsIOException {

// 目錄對象,描述了索引的存放位置,需要由 Path 進行初始化

Directory directory = FSDirectory.open(Paths.get(INDEX_DIR));

// 創建分詞器

Analyzer analyzer =newStandardAnalyzer();// 由分詞器對 IndexWriterConfig 進行初始化

IndexWriterConfig indexWriterConfig =newIndexWriterConfig(analyzer);

indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

IndexWriter indexWriter =newIndexWriter(directory, indexWriterConfig);

File file =newFile(DATA_DIR);

File[ ] files = file.listFiles();

if(files !=null) {

// 讀取並遍歷文本路徑下的所有文件,用於生成文檔及其索引

for(File f : files) {

// 創建文檔

Document document =newDocument();// 為文檔設置 Field

document.add(newStringField("filename", f.getName(), Field.Store.YES));

document.add(newTextField("content", FileUtils.readFileToString(f, Charset.defaultCharset()), Field.Store.YES));

document.add(newLongField("lastModify", f.lastModified(), Field.Store.YES));

// 寫入索引

indexWriter.addDocument(document);

}

}

indexWriter.close();

}

public static voidmain(String[ ] args)throwsIOException {

CreateIndex createIndex =newCreateIndex();

createIndex.createIndex();

}

}

運行完畢之後,發現 index 路徑下多了一些文件,即為文檔的索引。

4.4

查詢索引

public classSearchIndex{

public voidsearch() throwsIOException, ParseException {

// 打開索引所在路徑

Directory directory = FSDirectory.open(Paths.get(CreateIndex.INDEX_DIR));

IndexReader indexReader = DirectoryReader.open(directory);

IndexSearcher indexSearcher =newIndexSearcher(indexReader);

QueryParser queryParser =newQueryParser("content", new StandardAnalyzer());

Query query = queryParser.parse("from");

// 找到符合條件的前 10 條 Document 的索引的集合

TopDocs search = indexSearcher.search(query,10);

// 遍歷集合併列印文件名稱

for(ScoreDoc scoreDoc : search.scoreDocs) {

public static voidmain(String[] args)throwsIOException, ParseException {

SearchIndex searchIndex =newSearchIndex();

searchIndex.search();

}

}

查詢結果:

5. 理解索引

過程核心類

執行簡單的索引過程需要用到以下幾個類:

● IndexWriter

● Directory

● Analyzer

● Document

● Field

5.1

IndexWriter

IndexWriter(寫索引)是索引過程的核心組件,這個類負責創建新索引或者打開已有索引,以及向索引中添加、刪除或者是更新被索引文檔的信息。為開發者提供針對索引文件的寫入操作,但不能用於讀取或者搜索索引。IndexWriter 需要開闢一定的空間用來存儲索引,該功能可以由 Directory 完成。

5.2

Directory

Directory 描述了 Lucene 索引存放的位置。它是一個抽象類,其實現類負責具體指定索引的存儲路徑。在上面的例子中,我們使用 FSDirectory.open() 方法來獲取真實文件在文件系統中的存儲路徑,然後將她們依次傳遞給 IndexWriter 類的構造方法。

IndexWriter 不能直接索引文本,需要先由 Analyzer 將文本分割成獨立的單詞才行。

5.3

Analyzer

文本文件在被索引之前,需要經過 Analyzer 處理,Analyzer 由 IndexWriter 的構造方法來指定,負責從被索引文本文件中提取辭彙單元,並剔除剩下的無用信息。如果被索引的內容不是純文本文件,那就需要先將其轉換成文本文檔。

Analyzer 是一個抽象類,其實現類中:

● 有的用於跳過停用詞(指一些常用且不能幫 助區分文檔的詞,如a、an、the、in 和 on 等)

● 有的用於把辭彙轉換成小寫,以使得搜索過程不區分大小寫

● 等等

分析器的分析對象為文檔。

5.4

Document

Document 代表一些 域(Field) 的集合,可以將 Document 理解為虛擬文檔,如 Web頁面、郵件信息等。文檔的域代表文檔或者文檔相關的一些元數據。

Lucene 只處理文本和數字,Lucene 的內核本身只處理 java.lang.String 和 java.io.Reader 對象和本地數字類型

Document 對象的結構比較簡單,為一個多個 Field 對象的容器, Field 是指包含能被索引的文本內容的類。

5.5

Field

索引中,每個文檔都包含一個或者多個不同命名的域,這些域包含在 Field 類中。

每個域都有一個域名和對應的值,以及一組選項來精確控制 Lucene 索引操作各個域值。

6. 理解搜索

過程核心類

核心類:

● IndexSearcher

● Term

● Query

● TermQuery

● TocDocs

6.1

IndexSearcher

用於搜索 IndexWriter 所創建的索引,可以將它看做一個以只讀方式打開索引的類。

它需要利用 Directory 實例來掌握前期創建的索引,然後才能提供大量的搜索方法,最簡單的搜索方法是將單個 Query 對象和 int topN 所謂該方法的參數,返回一個 TopDocs 對象。

6.2

Term

Term 是搜索功能的基本單元,與 Field 對象類似,Term 對象包含一對字元串元素:域名和單詞,注意 Term 對象還與索引操作有關。

6.3

Query

Lucene 含有許多具體的 Query 子類

6.4

TermQuery

是 Lucene 提供的最基本的查詢類型,也是簡單的查詢類型之一,它用來匹配指定域中包含特定值的文檔。

6.5

TopDocs

TopDocs 類是一個簡單的容器指針,指針一般指向前 N 個排名的搜索結果,搜索結果即匹配查詢條件的文檔。TopDocs 會記錄前 N 個結果中每個結果的 int docID 和浮點型分數。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員食堂 的精彩文章:

TAG:程序員食堂 |