lucene的檢索算法屬於索引檢索,即用空間來換取時間,對需要檢索的文件、字符流進行全文索引,在檢索的時候對索引進行快速的檢索,得到檢索位置,這個位置記錄檢索詞出現的文件路徑或者某個關鍵詞。
analysis:分析器,切詞
document:索引存儲時的文檔結構管理器,類似表結構
index:索引管理,包括建立,刪除索引
queryParser:查詢分析器,實現查詢關鍵詞的運算
search:檢索管理,根據查詢條件,檢索得到結果
store:數據存儲管理,IO操作
Directory:索引存放的位置;lucene 提供了兩種索引存放的位置,一種是磁盤,一種是內存。
Hits:在搜索完成之後,需要把搜索結果返回並顯示給用戶,只有這樣才算是完成搜索的目的。
IndexWriter:用於更新或創建索引。
Lucene的索引結構是文檔(Document)形式的。
1.將文檔傳給分詞組件(Tokenizer),分詞組件根據標點符號和停詞將文檔分成詞元(Token),並將標點符號和停詞去掉。
2.再將詞元傳給語言處理組件(Linguistic Processor) ,詞元會變成最基本的詞根形式。
3.得到的詞元傳給索引組件(Indexer),索引組件處理得到索引結構,得到關鍵字、出現頻率、出現位置分別作為詞典文件
(Term Dictionary)、頻率文件(frequencies)和位置文件(positions)保存起來,然後通過二元搜索算法快速查找關鍵字。
示例:
一篇文檔有多種信息,如題目,作者,修改時間,內容等。
不同類型的信息用不同的Field 來表示,在本例子中,一共有兩類信息進行了索引,一個是文件路徑,一個是文件內容。
其中FileReader 的SRC_FILE 就表示要索引的源文件。
索引建立步驟:
1、創建Directory
2、創建Writer
3、創建文檔並且添加索引
4、查詢索引的基本信息
5、刪除和更新索引
public class HelloLucene {
public static void main(String[] args) throws IOException, ParseException {
// 0. Specify the analyzer for tokenizing text.
// The same analyzer should be used for indexing and searching
StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
// 1. create the index
Directory index = new RAMDirectory();
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);
IndexWriter w = new IndexWriter(index, config);
addDoc(w, "Lucene in Action", "193398817");
addDoc(w, "Lucene for Dummies", "55320055Z");
addDoc(w, "Managing Gigabytes", "55063554A");
addDoc(w, "The Art of Computer Science", "9900333X");
w.close();
// 2. query
String querystr = args.length > 0 ? args[0] : "lucene";
// the "title" arg specifies the default field to use
// when no field is explicitly specified in the query.
Query q = new QueryParser(Version.LUCENE_40, "title", analyzer).parse(querystr);
// 3. search
int hitsPerPage = 10;
IndexReader reader = DirectoryReader.open(index);
IndexSearcher searcher = new IndexSearcher(reader);
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
// 4. display results
System.out.println("Found " + hits.length + " hits.");
for(int i=0;i int docId = hits[i].doc; Document d = searcher.doc(docId); System.out.println((i + 1) + ". " + d.get("isbn") + "\t" + d.get("title")); } // reader can only be closed when there // is no need to access the documents any more. reader.close(); } private static void addDoc(IndexWriter w, String title, String isbn) throws IOException { Document doc = new Document(); doc.add(new TextField("title", title, Field.Store.YES)); // use a string field for isbn because we don't want it tokenized doc.add(new StringField("isbn", isbn, Field.Store.YES)); w.addDocument(doc); } } 搜索過程:示例如上 IndexReader 將磁盤上的索引信息讀入到內存,INDEX_DIR 就是索引文件存放的位置。
創建IndexSearcher 準備進行搜索。
創建Analyer 用來對查詢語句進行詞法分析和語言處理。
創建QueryParser 用來對查詢語句進行語法分析。
QueryParser 調用parser 進行語法分析,形成查詢語法樹,放到Query 中。
IndexSearcher 調用search 對查詢語法樹Query 進行搜索,得到結果TopScoreDocCollector 。
在Lucene中,詞典和倒排是分開存儲的,詞典存儲在.tii和.tis文件中,而倒排又分為兩部分存儲,第一部分是文檔號和詞頻信息,存儲在.frq中;另一部分是詞的位置信息,存儲在.prx文件中。
所謂正向信息:
lucene 在存儲它的全文索引結構時,是有層次結構的,
涉及到5個層次:索引(Index) –> 段(segment) –> 文檔(Document) –> 域(Field) –> 詞(Term)
索引(Index):一個目錄一個索引,在Lucene中一個索引是放在一個文件夾中的。
段(Segment):一個索引可以包含多個段,段與段之間是獨立的,添加新文檔可以生成新的段,不同的段可以合併。
文檔(Document):文檔是我們建索引的基本單位,不同的文檔是保存在不同的段中的,一個段可以包含多篇文檔。
域(Field):一篇文檔包含不同類型的信息,可以分開索引.
詞(Term):詞是索引的最小單位,是經過詞法分析和語言處理後的字符串。
所謂反向信息:
保存了詞典到倒排表的映射:詞(Term) –> 文檔(Document)
更多內容請關注每日編程。
閱讀更多 每日編程 的文章