建立索引lucene_用Lucene建立搜索索引
建立索引lucene
本文是我們名為“ Apache Lucene基礎(chǔ)知識 ”的學(xué)院課程的一部分。
在本課程中,您將了解Lucene。 您將了解為什么這樣的庫很重要,然后了解Lucene中搜索的工作方式。 此外,您將學(xué)習(xí)如何將Lucene Search集成到您自己的應(yīng)用程序中,以提供強大的搜索功能。 在這里查看 !
目錄
1.簡介 2.了解索引操作1.簡介
該索引是利用Lucene的任何組件的核心。 就像書籍的索引一樣,它組織所有數(shù)據(jù),以便可以快速訪問。 索引由包含一個或多個字段的文檔組成。 “文檔和字段”可以代表我們選擇的任何內(nèi)容,但一個常見的隱喻是“文檔”代表數(shù)據(jù)庫表中的條目,而“字段”類似于表中的字段。
2.了解索引操作
讓我們看一下Lucene搜索索引的圖形表示。
圖1
簡而言之,當(dāng)Lucene對文檔進行索引時,它會將其分解為許多術(shù)語。 然后,它將術(shù)語存儲在索引文件中,其中每個術(shù)語都與包含該術(shù)語的文檔相關(guān)聯(lián)。 我們可以把它當(dāng)作一個哈希表。 術(shù)語是使用分析器生成的,該分析器將每個單詞的詞根都提取出來。 發(fā)出查詢時,將通過用于構(gòu)建索引的同一分析器來處理該查詢,然后使用該分析器在索引中查找匹配項。 這提供了與查詢匹配的文檔列表。
現(xiàn)在,讓我們看一下整個Lucene搜索過程。
基本概念是索引,文檔,字段和術(shù)語。
2.1倒排索引
索引存儲有關(guān)術(shù)語的統(tǒng)計信息,以使基于術(shù)語的搜索更加高效。 Lucene的索引屬于稱為反向索引的索引族。 這是因為它可以長期列出包含它的文檔。 這與自然關(guān)系相反,在自然關(guān)系中文檔列出了術(shù)語。
2.2字段類型
在Lucene中,可以存儲字段,在這種情況下,它們的文本按原樣以非反轉(zhuǎn)的方式存儲在索引中。 反轉(zhuǎn)的字段稱為索引。 字段可以被存儲和被索引。
可以將字段的文本標(biāo)記為要索引的術(shù)語,或者可以將字段的文本從字面上用作要索引的術(shù)語。 大多數(shù)字段都是標(biāo)記化的,但有時對于某些標(biāo)識符字段按字面意義進行索引很有用。
2.3細(xì)分
Lucene索引可以由多個子索引或段組成。 每個段都是完全獨立的索引,可以分別進行搜索。 索引按以下方式演變:
2.4文件編號
在內(nèi)部,Lucene通過整數(shù)文檔號引用文檔。 添加到索引的第一個文檔編號為零,并且隨后添加的每個文檔的編號都比前一個大。
請注意,文檔編號可能會更改,因此在將這些編號存儲在Lucene之外時應(yīng)格外小心。 特別是在以下情況下,數(shù)字可能會更改:
存儲在每個段中的數(shù)字僅在該段內(nèi)是唯一的,并且必須進行轉(zhuǎn)換才能在更大的上下文中使用它們。 標(biāo)準(zhǔn)技術(shù)是根據(jù)該段中使用的數(shù)字范圍為每個段分配一個值范圍。 要將文檔編號從段轉(zhuǎn)換為外部值,需要添加段的基本文檔編號。 要將外部值轉(zhuǎn)換回特定于細(xì)分的值,可以通過外部值所在的范圍來標(biāo)識細(xì)分,然后減去細(xì)分的基值。 例如,可以合并兩個五個文檔的段,以便第一個段的基值為零,第二個為五個。 第二段中的文檔3的外部值為8。
刪除文檔后,在編號中會留出空白。 隨著索引通過合并的發(fā)展,這些最終被刪除。 合并段時刪除已刪除的文檔。 因此,新合并的段在編號上沒有空白。
2.5搜索索引
搜索索引由javascript函數(shù)定義。 它以類似于視圖的地圖功能的方式運行在所有文檔上,并定義了搜索可查詢的字段。 搜索索引是數(shù)據(jù)庫的一種變體。 它與RDBMS相似,因為它需要快速查找密鑰,但是大部分?jǐn)?shù)據(jù)駐留在輔助存儲上。
3.創(chuàng)建索引
到目前為止,我們已經(jīng)看到了Lucene索引的所有組成部分。 在本節(jié)中,我們將使用Lucene索引創(chuàng)建文檔索引。
考慮一個學(xué)生在其中提交年度雜志文章的項目。 輸入控制臺包含用于學(xué)生姓名,文章標(biāo)題,文章類別和文章正文的選項。 我們假設(shè)該項目正在網(wǎng)絡(luò)中運行并且可以通過它進行訪問。 要為這篇文章建立索引,我們將需要文章本身,作者姓名,撰寫日期,文章主題,文章標(biāo)題以及文件所在的URL。 利用這些信息,我們可以構(gòu)建一個程序,該程序可以正確索引文章以使其易于查找。
讓我們看一下我們類的基本框架,包括我們將需要的所有導(dǎo)入。
import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Hits; import java.util.Date; public class ArticleIndexer { }我們需要添加的第一件事是將文章轉(zhuǎn)換為Document對象的方法。
為此,我們將使用方法createDocument() ,
private Document createDocument(String article, String author,String title, String topic,String url, Date dateWritten) { Document document = new Document();document.add(Field.Text("author", author));document.add(Field.Text("title", title));document.add(Field.Text("topic", topic));document.add(Field.UnIndexed("url", url));document.add(Field.Keyword("date", dateWritten));document.add(Field.UnStored("article", article));return document;}首先,我們創(chuàng)建一個新的Document對象。 我們需要做的下一步是將文章的不同部分添加到Document 。 我們?yōu)槊總€部分提供的名稱完全是任意的,并且像HashMap鍵一樣工作。 使用的名稱必須是String 。 Document的add方法將采用一個Field對象,該對象是使用Field類提供的靜態(tài)方法之一構(gòu)建的。 提供了四種將Field對象添加到Document的方法。
Field.Keyword –數(shù)據(jù)已存儲并建立索引,但未標(biāo)記化。 這對于應(yīng)保留不變的數(shù)據(jù)(例如日期)最有用。 實際上,Field.Keyword可以將Date對象作為輸入。
Field.Text –數(shù)據(jù)被存儲,索引和標(biāo)記化。 Field.Text字段不應(yīng)用于諸如文章本身之類的大量數(shù)據(jù),因為索引將變得非常大,因為它將包含文章的完整副本以及標(biāo)記化的版本。
Field.UnStored –不存儲數(shù)據(jù),但對其進行索引和標(biāo)記化。 大量的數(shù)據(jù)(如文章的文本)應(yīng)放置在未存儲的索引中。
Field.UnIndexed –數(shù)據(jù)已存儲但未建立索引或標(biāo)記化。 它與要與搜索結(jié)果一起返回的數(shù)據(jù)一起使用,但實際上不會在該數(shù)據(jù)上進行搜索。 在我們的示例中,由于我們不允許搜索URL,因此沒有理由對其進行索引,但是我們希望在找到搜索結(jié)果后將其返回給我們。
現(xiàn)在我們有了一個Document對象,我們需要獲得一個IndexWriter來將此Document寫入索引。
String indexDirectory = "lucene-index"; private void indexDocument(Document document) throws Exception {Analyzer analyzer = new StandardAnalyzer();IndexWriter writer = new IndexWriter(indexDirectory, analyzer, false);writer.addDocument(document);writer.optimize();writer.close();}我們首先創(chuàng)建一個StandardAnalyzer ,然后使用分析器創(chuàng)建一個IndexWriter 。 在構(gòu)造函數(shù)中,我們必須指定索引將駐留的目錄。 構(gòu)造函數(shù)末尾的布爾值告訴IndexWriter是創(chuàng)建新索引還是添加到現(xiàn)有索引。 在將新文檔添加到現(xiàn)有索引時,我們將指定false。 然后,我們將Document添加到索引。 最后,我們優(yōu)化然后關(guān)閉索引。 如果要添加多個Document對象,則應(yīng)始終進行優(yōu)化,然后在將所有Document對象都添加到索引之后關(guān)閉索引。
現(xiàn)在,我們只需要添加一種將各個部分組合在一起的方法即可。
為了驅(qū)動索引??操作,我們將編寫一個indexArticle()一些參數(shù)的方法indexArticle() 。
public void indexArticle(String article, String author,String title, String topic,String url, Date dateWritten)throws Exception {Document document = createDocument(article, author,title, topic,url, dateWritten);indexDocument(document);}對文章運行此操作會將該文章添加到索引中。 將IndexWriter構(gòu)造函數(shù)中的布爾值更改為true會創(chuàng)建一個索引,因此我們應(yīng)該在第一次創(chuàng)建索引以及每次要從頭開始重建索引時使用它。 現(xiàn)在我們已經(jīng)構(gòu)建了索引,我們需要在索引中搜索文章。
索引存儲為單個目錄中的一組文件。
索引由任意數(shù)量的獨立段組成,這些段存儲有關(guān)已索引文檔子集的信息。 每個段都有自己的術(shù)語詞典,術(shù)語詞典索引和文檔存儲(存儲的字段值)。 所有段數(shù)據(jù)都存儲在_xxxxx.cfs文件中,其中xxxxx是段名稱。
創(chuàng)建索引段文件后,將無法對其進行更新。 新文檔將添加到新段中。 刪除的文檔僅在可選的.del文件中標(biāo)記為已刪除。
4.基本索引操作
索引數(shù)據(jù)
Lucene讓我們可以以文本格式索引任何可用數(shù)據(jù)。 Lucene可以用于幾乎所有數(shù)據(jù)源,只要可以從中提取文本信息即可。 我們可以使用Lucene索引和搜索存儲在HTML文檔,Microsoft Word文檔,PDF文件等中的數(shù)據(jù)。 索引數(shù)據(jù)的第一步是使其以簡單文本格式可用。 可以使用自定義解析器和數(shù)據(jù)轉(zhuǎn)換器。
索引過程
索引編制是將文本數(shù)據(jù)轉(zhuǎn)換為便于快速搜索的格式的過程。 一個簡單的類比是您在書末找到的索引:該索引將您指向書中出現(xiàn)的主題的位置。
Lucene將輸入數(shù)據(jù)存儲在稱為反向索引的數(shù)據(jù)結(jié)構(gòu)中,該結(jié)構(gòu)作為一組索引文件存儲在文件系統(tǒng)或內(nèi)存中。 大多數(shù)Web搜索引擎使用反向索引。 它使用戶可以執(zhí)行快速的關(guān)鍵字查找,并找到與給定查詢匹配的文檔。 在將文本數(shù)據(jù)添加到索引之前,它需要由分析器處理(使用分析過程)。
分析
分析將文本數(shù)據(jù)轉(zhuǎn)換為基本搜索單位,稱為術(shù)語。 在分析過程中,文本數(shù)據(jù)將經(jīng)歷多個操作:提取單詞,刪除常用單詞,忽略標(biāo)點符號,將單詞簡化為根形式,將單詞更改為小寫字母等。分析僅在建立索引和查詢解析之前進行。 分析將文本數(shù)據(jù)轉(zhuǎn)換為標(biāo)記,并將這些標(biāo)記作為術(shù)語添加到Lucene索引中。
Lucene帶有各種內(nèi)置分析器,例如SimpleAnalyzer , StandardAnalyzer , StopAnalyzer , SnowballAnalyzer等。 這些不同之處在于它們標(biāo)記文本和應(yīng)用過濾器的方式。 由于分析會在建立索引之前刪除單詞,因此會減小索引大小,但會對查詢處理的精度產(chǎn)生負(fù)面影響。 您可以使用Lucene提供的基本構(gòu)建塊來創(chuàng)建自定義分析器,從而對分析過程進行更多控制。 表1顯示了一些內(nèi)置分析儀及其處理數(shù)據(jù)的方式。
4.1核心索引類
目錄
表示索引文件存儲位置的抽象類。 通常主要使用兩個子類:
FSDirectory —目錄的實現(xiàn),在實際的文件系統(tǒng)中存儲索引。 這對于大索引很有用。
RAMDirectory —將所有索引存儲在內(nèi)存中的實現(xiàn)。 這適用于較小的索引,這些索引可以完全加載到內(nèi)存中,并在應(yīng)用程序終止時銷毀。 由于索引保存在內(nèi)存中,因此速度相對較快。
分析儀
如上所述,分析器負(fù)責(zé)預(yù)處理文本數(shù)據(jù)并將其轉(zhuǎn)換為存儲在索引中的令牌。 IndexWriter接受用于對數(shù)據(jù)建立索引之前對其進行標(biāo)記化的分析器。 要正確索引文本,您應(yīng)該使用適合需要索引的文本語言的分析器。
默認(rèn)分析器適用于英語。 Lucene沙箱中還有其他幾種分析器,包括中文,日文和韓文的分析器。
IndexDeletionPolicy
用于實現(xiàn)自定義從索引目錄中刪除過時提交的策略的接口。 默認(rèn)的刪除策略是KeepOnlyLastCommitDeletionPolicy ,該策略僅保留最新的提交,并在完成新提交后立即刪除所有先前的提交。
索引作家
創(chuàng)建或維護索引的類。 它的構(gòu)造函數(shù)接受一個布爾值,該布爾值確定是創(chuàng)建新索引還是打開現(xiàn)有索引。 它提供了添加,刪除或更新索引中文檔的方法。
最初對索引所做的更改將存儲在內(nèi)存中,并定期刷新到索引目錄中。 IndexWriter公開了幾個字段,這些字段控制索引在內(nèi)存中的緩沖方式以及如何將其寫入磁盤。 除非調(diào)用IndexWriter的commit或close方法,否則對IndexReader不到對索引所做的更改。 IndexWriter為目錄創(chuàng)建一個鎖定文件,以防止索引同時更新導(dǎo)致索引損壞。 IndexWriter允許用戶指定可選的索引刪除策略。
4.2將數(shù)據(jù)添加到索引
將文本數(shù)據(jù)添加到索引涉及兩個類。
字段表示在搜索中查詢或檢索的一條數(shù)據(jù)。 Field類封裝一個字段名稱及其值。 Lucene提供了一些選項來指定是否需要對字段進行索引或分析以及是否需要存儲其值。 在創(chuàng)建字段實例時可以傳遞這些選項。 下表顯示了字段元數(shù)據(jù)選項的詳細(xì)信息。
| 選項 | 描述 |
| Field.Store.Yes | 用于存儲字段的值。 適用于顯示搜索結(jié)果的字段,例如文件路徑和URL。 |
| Field.Store.No | 字段值未存儲-例如,電子郵件正文。 |
| Field.Index.No | 適用于未搜索的字段-通常與存儲的字段一起使用,例如文件路徑。 |
| Field.Index.ANALYZED | 用于索引但未分析的字段。 它完整??保留了字段的原始值,例如日期和個人名稱。 |
| Field.Index.NOT_ANALYZED | 用于索引但未分析的字段。 它完整??保留了字段的原始值,例如日期和個人名稱。 |
字段元數(shù)據(jù)選項的詳細(xì)信息
而文檔是字段的集合。 Lucene還支持增強文檔和字段,如果要重視某些索引數(shù)據(jù),這是一個有用的功能。 為文本文件建立索引包括將文本數(shù)據(jù)包裝在字段中,創(chuàng)建文檔,使用字段填充文本,以及使用IndexWriter將文檔添加到索引中。
5.文件和領(lǐng)域
如您先前所見,文檔是索引和搜索過程的單元。
5.1文件
文檔是一組字段。 每個字段都有一個名稱和一個文本值。 字段可以與文檔一起存儲,在這種情況下,它會隨文檔的搜索命中一起返回。 因此,每個文檔通常應(yīng)包含一個或多個唯一標(biāo)識它的存儲字段。
您將文檔添加到索引,并且在執(zhí)行搜索之后,您將獲得結(jié)果列表,它們是文檔。 文檔只是字段的非結(jié)構(gòu)化集合。
5.2領(lǐng)域
字段是Lucene.net的實際內(nèi)容所有者:它們基本上是一個哈希表,具有名稱和值。 如果我們有無限的磁盤空間和無限的處理能力,那就是我們所需要知道的。 但是不幸的是,磁盤空間和處理能力受到限制,因此您不能僅僅分析所有內(nèi)容并將其存儲到索引中。 但是Lucene.net提供了將字段添加到索引的不同方法。
Lucene提供了四種不同類型的字段供開發(fā)人員選擇: Keyword , UnIndexed , UnStored和Text 。 您應(yīng)該使用哪種字段類型取決于您要如何使用該字段及其值。
關(guān)鍵字字段未標(biāo)記,但被逐字索引并存儲在索引中。 此字段適用于應(yīng)完整保留原始值的字段,例如URL,日期,個人姓名,社會保險號,電話號碼等。
未索引字段既沒有標(biāo)記也沒有索引,但它們的值存儲在逐字索引中。 該字段適用于需要與搜索結(jié)果一起顯示但絕不會直接搜索其值的字段。 由于未對該類型的字段編制索引,因此對其進行搜索很慢。 由于此類型的字段的原始值存儲在索引中,因此如果存在索引大小的問題,則此類型不適合存儲值非常大的字段。
未存儲字段與未索引字段相反。 此類型的字段已標(biāo)記并建立索引,但未存儲在索引中。 此字段適用于索引大量不需要以其原始形式檢索的文本,例如網(wǎng)頁正文或任何其他類型的文本文檔。
文本字段被標(biāo)記,索引并存儲在索引中。 這意味著可以搜索這種類型的字段,但是請注意存儲為“文本”字段的字段的大小。
如果您回顧一下LuceneIndexExample類,您將看到我使用了Text字段:
document.add(Field.Text("fieldname", text));如果要更改字段fieldname的類型,我們將調(diào)用Field類的其他方法之一:
document.add(Field.Keyword("fieldname", text));要么
document.add(Field.UnIndexed("fieldname", text));要么
document.add(Field.UnStored("fieldname", text));盡管Field.Text , Field.Keyword , Field.UnIndexed和Field.UnStored調(diào)用最初看起來像是對構(gòu)造函數(shù)的調(diào)用,但實際上它們只是對不同F(xiàn)ield類方法的調(diào)用。 表1總結(jié)了不同的字段類型。
| 現(xiàn)場方法/類型 | 代幣化 | 索引 | 已儲存 |
| Field.Keyword(String, String) | 沒有 | 是 | 是 |
| Field.UnIndexed(String, String) | 沒有 | 沒有 | 是 |
| Field.UnStored(String, String) | 是 | 是 | 沒有 |
| Field.Text(String, String) | 是 | 是 | 是 |
| Field.Text(String, Reader) | 是 | 是 | 沒有 |
表1:不同字段類型的概述。
5.3在Lucene中增強文檔
在信息檢索中,文檔與搜索的相關(guān)性通過與查詢的相似程度來衡量。 Lucene中實現(xiàn)了幾種相似性模型,您可以通過擴展相似性類并使用Lucene保存的索引統(tǒng)計信息來實現(xiàn)自己的相似性模型。 還可以為文檔分配靜態(tài)分?jǐn)?shù),以表示它們在整體語料庫中的重要性,而與正在執(zhí)行的查詢無關(guān),例如其受歡迎程度,評分或PageRank。
在Lucene 4.0之前,您可以通過調(diào)用document.setBoost為文檔分配靜態(tài)分?jǐn)?shù)。 在內(nèi)部,通過將字段的提升因子乘以文檔的提升因子,將提升應(yīng)用于文檔的每個字段。 但是,這永遠無法正常工作,并且取決于所執(zhí)行查詢的類型,可能根本不會影響文檔的排名。
通過在Lucene中添加DocValues,增強文檔就像添加NumericDocValuesField并將其用于CustomScoreQuery一樣簡單, CustomScoreQuery將計算所得的分?jǐn)?shù)乘以“ boost”字段的值。 下面的代碼示例說明了如何實現(xiàn)此目的:
// add two documents to the index Document doc = new Document(); doc.add(new TextField("f", "test document", Store.NO)); doc.add(new NumericDocValuesField("boost", 1L)); writer.addDocument(doc); doc = new Document(); doc.add(new TextField("f", "test document", Store.NO)); doc.add(new NumericDocValuesField("boost", 2L)); writer.addDocument(doc); // search for 'test' while boosting by field 'boost' Query baseQuery = new TermQuery(new Term("f", "test")); Query boostQuery = new FunctionQuery(new LongFieldSource("boost")); Query q = new CustomScoreQuery(baseQuery, boostQuery); searcher.search(q, 10);通過編寫一個簡單的公式,新的Expressions模塊也可以用于增強文檔,如下所示。 盡管比使用CustomScoreQuery更為冗長,但它通過計算更復(fù)雜的公式(例如sqrt(_score)+ ln(boost))來提高效率。
Expression expr = JavascriptCompiler.compile("_score * boost"); SimpleBindings bindings = new SimpleBindings(); bindings.add(new SortField("_score", SortField.Type.SCORE)); bindings.add(new SortField("boost", SortField.Type.LONG)); Sort sort = new Sort(expr.getSortField(bindings, true)); searcher.search(baseQuery, null, 10, sort);既然Lucene允許在不重新索引文檔的情況下更新NumericDocValuesField ,您就可以將頻繁變化的字段(受歡迎程度,評分,價格,最后修改時間…)合并到提升因素中,而無需每次對其中任何一個更改時都重新索引文檔。
翻譯自: https://www.javacodegeeks.com/2015/09/building-a-search-index-with-lucene.html
建立索引lucene
總結(jié)
以上是生活随笔為你收集整理的建立索引lucene_用Lucene建立搜索索引的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lucene 查询示例_Lucene查询
- 下一篇: linux查看(dns linux 查看