搜索引擎lucene實現--二半吊子的論調之體系結構


寫這個東西就是兩個目的,一是讓自己頭腦清醒,一是讓別人把咱的頭腦弄清醒。技術這個東西跟本能一個樣,只要你願意用成就本能的方式去學習技術,誰都可以成就自己。

因為咱不是文科出身,工作了六年,也沒有那些牛逼人士的韌力和魄力,曾經就想着能多寫寫技術博客,但總是沒有堅持下去(深嘆一口氣,你可別像我這樣。。)。前些日子又看了一下《康熙王朝》(陳道明演的),被里面的一句話(一言之虛,百患叢生; 一事之虛,遺害終生。)給擊蒙了,於是重新想着堅持下去。剛好要跟同事分享lucene,那么也就多學,多看,多想,多寫了。

OK,言歸正傳,到底搜索引擎有多神秘?

對我來說,lucene的出現,沒有多少影響,因為當初我還在一個小公司里面糊里糊塗地混日子,而雖然聽說過這個東西,但沒有用過,僅了解了一下。但自從去了那個網絡公司之后,要做搜索系統,我就切實地接觸到了這個開源神器。至少在一定程度上講,讓我覺得Google,百度不是那么神奇的公司了。因為他們就是用超大規模的爬蟲,倒排表,超大規模的緩存和我不知道的超大的things。

小差時刻:作為一個非計算機專業的從業人員,從一定程度上講,個人表示很慚愧。盡管有編程之熱情,但卻沒有徹底地鑽研從業用到的每個組成部分,這實在有點非專業的風格。我想這個浮躁的社會可能會讓很多人變成(編程)這樣,Matrix造就了我們追求成果不管原理的工作方式。(抱怨一下,但這是自我深深的反省。)

看一段lucene官網的示例代碼:

 1 import org.apache.lucene.analysis.Analyzer;
 2 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 3 import org.apache.lucene.document.Document;
 4 import org.apache.lucene.document.Field;
 5 import org.apache.lucene.document.TextField;
 6 import org.apache.lucene.index.DirectoryReader;
 7 import org.apache.lucene.index.IndexWriter;
 8 import org.apache.lucene.index.IndexWriterConfig;
 9 import org.apache.lucene.queryparser.classic.QueryParser;
10 import org.apache.lucene.search.IndexSearcher;
11 import org.apache.lucene.search.Query;
12 import org.apache.lucene.search.ScoreDoc;
13 import org.apache.lucene.store.Directory;
14 import org.apache.lucene.store.RAMDirectory;
15 import org.apache.lucene.util.Version;
16 
17 public final class TestLucene {
18 
19     public static void main(String[] args) throws Exception{
20         Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT);
21 
22         // Store the index in memory:
23         Directory directory = new RAMDirectory();
24         // To store an index on disk, use this instead:
25         //Directory directory = FSDirectory.open("/tmp/testindex");
26         IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_CURRENT, analyzer);
27         IndexWriter iwriter = new IndexWriter(directory, config);
28         Document doc = new Document();
29         String text = "This is the text to be indexed.";
30         doc.add(new Field("fieldname", text, TextField.TYPE_STORED));
31         iwriter.addDocument(doc);
32         iwriter.close();
33         
34         // Now search the index:
35         DirectoryReader ireader = DirectoryReader.open(directory);
36         IndexSearcher isearcher = new IndexSearcher(ireader);
37         // Parse a simple query that searches for "text":
38         QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, "fieldname", analyzer);
39         Query query = parser.parse("text");
40         ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs;
41         // Iterate through the results:
42         for (int i = 0; i < hits.length; i++) {
43           Document hitDoc = isearcher.doc(hits[i].doc);
44           System.out.println(hitDoc.get("fieldname"));
45         }
46         ireader.close();
47         directory.close();
48     }
49     
50 }

聲明:以上這段代碼,main里面的代碼都是取自lucene官網的。但也要特別說明一下,在maven pom.xml里面,對於lucene4.0版本的依賴配置如下:

<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>4.0.0</version>
</dependency>

好像3.x版本的不需要這么多配置的吧(好像又好久沒跟進lucene測試了。。呵呵)

僅僅從這個demo的import里面,我們能看到lucene的基本功能結構分割:

 

Lucene是一個文本內容的全文檢索系統,從上圖我們也可以看出lucene的確有比較明確且抽象的架構設計。

IndexWriter:接收業務數據,並將索引好的數據寫入到Store中。IndexWriter在接收數據時,主要依靠封裝了文本內容及其元數據的Document(org.apache.lucene.document,夾縫中引用一下,實在是委屈了Document,它也是具有皇室直系血統的類,非常重要。),它在org.apache.lucene.index包中。index包主要管理索引創建階段用到的各種類,如IndexReader, IndexWriter....(還有很多底層類,不一一列舉,但后面在詳細說明時,會一一分析。)

Store:這是一個相對底層的組織,對應包為org.apache.lucene.store,其主要包含與索引數據文件讀寫管理相關的各種類。

IndexSearcher: 這個是使用Query數據對索引數據進行檢索的類。猜得出來,它在org.apache.lucene.search中。

QueryParser:它也是存在於org.apache.lucene.search中,並且其主要職責是解析用戶的輸入字符串,並返回Query對象,然后供IndexSearcher使用,其對IndexSearcher的重要性跟Docment之於IndexWriter有的一拼。

Analyzer:最后才說到Analyzer,並不是說它不重要,相反它極其重要。Analyzer類主要用戶對文本內容進行分詞處理,而分詞質量的好壞關系到搜索結果的相關度,所以也就有了針對不同文化和語言的各種Analyzer。正如圖中展現的,建立和查詢索引時都要用到它,是居家旅行的必備良葯。

對於網絡用戶來說,他們只需要關心query data(就是他們想搜的關鍵詞或者句子),經過Parser解析成關鍵字的query(queryparser的結果),經由IndexSearcher來查詢Indexed Data,並返回結果。而我們在對目標數據建索引的過程,則是經由IndexWriter來解析和分解處理,然后將解析的結果(這是個big problem)保存成Indexed Data。

這里要區分一下,網絡用戶他們只想查找關心的數據,所以他們輸入:關鍵詞;而我們開發者則有業務數據。這里就是說,在使用lucene時,是否需要想想以下幾個方面:

數據獲取:提供用於接收業務數據的接口,搜索請求處理接口;

lucene封裝:組裝索引Document的接口,返回結果的封裝接口,更重要的是log接口(統計和實驗);

 

瞻前顧后,咱會從Analyzer,Document,Index,Search and Store幾個方面,給各位分享一下lucene的情況。

一點點來,不着急。。。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM