lucene_Lucene组件概述
lucene
本文是我們名為“ Apache Lucene基礎知識 ”的學院課程的一部分。
在本課程中,您將了解Lucene。 您將了解為什么這樣的庫很重要,然后了解Lucene中搜索的工作方式。 此外,您將學習如何將Lucene Search集成到您自己的應用程序中,以提供強大的搜索功能。 在這里查看 !
目錄
1.信息超載/爆炸 2.索引非結構化數據的組件 3.數據搜索的組成部分 4.使用Apache Lucene的簡單搜索應用程序 5.下載源代碼1.信息超載/爆炸
如今,應用程序中的搜索功能正變得越來越重要。 畢竟,Web僅僅與信息有關,而所有與在正確的時間和正確的手中獲取信息有關。
信息爆炸的形式是,現代世界中已發布的數字信息量Swift增加,以及大量原始數據和非結構化數據的影響。 這種信息爆炸導致我們所有人的信息過載持續不斷。
現在,信息超載已成為世界各地辦公室中的普遍現象。 一些原因包括:
- 沒有簡化或過濾以使其更短
- 書寫不清晰,所以人們不得不花更多的時間來理解它們
- 包含事實錯誤或不一致之處-需要進一步研究
解
盡管沒有上述問題的簡單且單一的解決方案,但是可以使用一些方法來緩解該問題。
這些包括:
現在,除此以外,我們還可以使用開源搜索庫Apache Lucene實施信息檢索解決方案,只要我們可以從內容存儲庫中獲取文本數據,它就可以從此類非結構化內容中檢索信息。
搜索應用程序的簡短概述
當然,以上用例并不是從龐大的信息存儲庫中所有基于文本的搜索和信息檢索的唯一解決方案。 在某些情況下,普通的數據庫搜索功能就足夠了。 其他工具(例如Apache Hadoop)對數據處理的要求也是可行的選擇。
2.索引非結構化數據的組件
索引組件維護文件的目錄,這些目錄可供用戶檢索文件。 索引組件是一項可選功能,應安裝在用戶可以訪問以進行文件檢索的任何服務器上。 索引組件支持按文件,文件版本和近期活動進行搜索。
讓我們研究與Lucene Indexing相關的一些術語:
索引實體
存儲在Lucene索引存儲庫中的那些文件或信息稱為索引實體。
每個Lucene索引由一個由名稱唯一標識的索引管理器管理。 在大多數情況下,索引實體和單個IndexManager之間也存在一對一關系(管理索引)。 索引分片和索引共享的用例除外。 當單個實體的索引太大而索引操作使應用程序變慢時,可以應用前者。 在這種情況下,單個實體被索引為多個索引,每個索引都有自己的索引管理器。 后者是索引共享,是將多個實體索引到同一Lucene索引中的功能。
分片索引
在某些情況下,將給定實體的索引數據拆分(分片)為多個Lucene索引可能很有用。
分片的可能用例是:
共享索引
從技術上講,可以將多個實體的信息存儲到單個Lucene索引中。 有兩種方法可以實現此目的:
3.數據搜索的組成部分
核心索引類
Lucene能夠獲得快速的搜索響應,因為它不是直接搜索文本,而是搜索索引。 這相當于通過搜索書后的索引來檢索與關鍵字相關的書中的頁面,而不是在書的每一頁中搜索單詞。
這種類型的索引稱為反向索引,因為它會將以頁面為中心的數據結構(page-> words)轉換為以關鍵字為中心的數據結構(word-> pages)。
我們可以相應地整理核心索引類,
要創建索引,首先要做的是創建一個IndexWriter對象。 IndexWriter對象用于創建索引并向該索引添加新的索引條目(即Documents)。 您可以創建一個IndexWriter ,如下所示:
IndexWriter indexWriter = new IndexWriter("index-directory", new StandardAnalyzer(), true);第一個參數指定將在其中創建Lucene索引的目錄,在本例中為index-directory。 第二個參數指定在Lucene為您的數據建立索引時將使用的“文檔解析器”或“文檔分析器”。 在這里,我們為此使用StandardAnalyzer 。 有關Lucene分析儀的更多詳細信息將很快出現。 第三個參數告訴Lucene如果尚未在目錄中創建索引,則創建一個新索引。
文檔是索引和搜索過程的單位。
字段是Lucene的實際內容所有者。 它們基本上是一個具有名稱和值的哈希表。
IndexWriter創建并維護索引。
構造函數的create參數確定是創建新索引還是打開現有索引。 即使讀者正在使用索引,我們也可以使用“ create = true”打開索引。 舊的讀者將繼續搜索他們已打開的“時間點”快照,直到重新打開后才能看到新創建的索引。 還有一些沒有create參數的構造函數,如果提供的路徑上沒有索引,則會創建新索引,否則將打開現有索引。
自上次刷新以來(以較早者為準),在上述方法調用過程中所做的更改將存儲在內存中,并在有足夠的緩沖刪除或添加的文檔時觸發刷新。 沖洗也可以被強制調用。 進行刷新時,未完成的刪除和添加的文檔都將刷新到索引。 刷新也可能觸發一個或多個段合并。
構造函數的可選autoCommit參數控制對讀取相同索引的IndexReader實例IndexReader更改的可見性。 如果為false,則在調用close()之前看不到更改。 更改仍將作為新文件刷新到目錄中,但不會被提交(不會寫入新的segment_N文件引用新文件),直到調用close()為止。 如果在close() )之前發生了嚴重錯誤(例如JVM崩潰),則索引將不反映所做的任何更改(它將保持其初始狀態)。 我們還可以調用abort() ,它在不進行任何更改的情況下關閉編寫器,并刪除所有已刷新但現在未引用的索引文件。 此模式對于防止讀者在不好的時間刷新(例如在完成所有刪除之后但在完成添加之前)很有用。 它也可以用于實現簡單的單作者事務性語義(“全部或全部”)。
當autoCommit為true時,則每次刷新也是一次提交。 在這種模式下運行時,應記住一件事,即在進行優化或段合并時,讀者不應刷新,因為這會占用大量磁盤空間。
無論autoCommit如何, IndexReader或IndexSearcher只會在打開索引的“時間點”看到該索引。 打開閱讀器后,提交給索引的任何更改將不可見,直到重新打開閱讀器為止。
如果在一段時間內不再添加更多文檔,并且需要最佳搜索性能,則應在關閉索引之前調用優化方法。
打開IndexWriter會為使用中的目錄創建一個鎖定文件。 嘗試在同一目錄上打開另一個IndexWriter將導致LockObtainFailedException 。 如果使用同一目錄上的IndexReader從索引中刪除文檔,也會引發LockObtainFailedException 。
核心搜索課程
核心搜索類是:
Lucene使用恰當命名的IndexReader實例從索引中讀取數據。
Lucene提供了執行實際搜索的IndexSearcher類。 每個索引搜索器都會包裝一個索引讀取器,以獲取索引數據的句柄。 有了索引搜索器后,我們可以為其提供查詢并按得分順序枚舉結果。 除了索引閱讀器之外,在索引搜索器中實際上沒有什么可配置的。
IndexSearcher實例是完全線程安全的,這意味著多個線程可以同時調用其任何方法。 如果應用程序需要外部同步,則無需在IndexSearcher實例上進行同步。 我們可以使用我們自己的(非Lucene)對象。
這是IndexReader類的語法:
IndexSearcher is = new IndexSearcher(path);查詢分為術語和運算符。 術語有兩種:單項和短語。
單個術語是一個單詞,例如“ test”或“ hello”。
詞組是由雙引號括起來的一組單詞,例如“ hello User”。
可以將多個術語與布爾運算符組合在一起以形成更復雜的查詢。
Lucene支持字段數據,Search Lucene API模塊經常在分面搜索中使用這些數據。 默認情況下,Search Lucene API搜索內容字段。 但是,您可以通過鍵入字段名稱后跟冒號“:”和我們要查找的術語來搜索特定字段中的數據。
例如,如果我們搜索名為“ The Right Way”的節點,其中包含文本“ go”,則可以輸入:
title:"The Right Way" AND contents:go要么
title:"The Right Way" AND go由于內容是默認字段,因此不需要字段指示符。
該字段僅對其直接在前的術語有效,因此查詢
title:Right Way只會在標題字段中找到“右”。 它將嘗試在默認字段(本例中為內容字段)中查找“ way”。
下面列出了所有可用的字段類型,
TopDocs是文檔的集合,這些文檔在使用查詢字符串進行搜索后進行了排序。 最匹配的文檔在TopDocs頂部列出。
對于搜索操作,需要一個IndexSearcher類,該類實現了主要的搜索方法。 對于每次搜索,都需要一個新的Query對象,并且可以從QueryParser實例中獲得該對象。 請注意,必須使用與創建索引相同的分析器類型來創建QueryParser ,在本例中為SimpleAnalyzer 。 根據JavaDocs的說法,Version也用作構造函數參數,并且是一個“被某些類用來在Lucene的各個發行版之間匹配版本兼容性”的類。
當由IndexSearcher執行搜索時,將作為執行結果返回TopDocs對象。 此類僅表示搜索結果,并允許我們檢索ScoreDoc對象。 使用ScoreDocs我們找到符合搜索條件的文檔,然后從這些文檔中檢索所需的信息。 讓我們看看所有這些都在起作用。
4.使用Apache Lucene的簡單搜索應用程序
在開始我們的第一個搜索應用程序之前,我們必須下載最新版本的Lucene。
我們已經下載了4.6版的Lucene jar文件。
接下來,我們必須構建一個名為“ LuceneWink”的項目,并將jar文件添加到該項目的類路徑中。
在開始運行搜索查詢之前,我們需要構建一個索引,將針對該索引執行查詢。 這將在名為IndexWriter的類的幫助下完成,該類是創建和維護索引的類。 IndexWriter接收文檔作為輸入,其中文檔是索引和搜索的單位。 每個Document實際上是一組字段,并且每個字段都有一個名稱和一個文本值。 要創建IndexWriter ,需要一個分析器。 此類是抽象的,我們將使用的具體實現是SimpleAnalyzer 。
我們將嘗試找出包含將在以下應用程序中作為查詢提供的字符串的文件。
因此,我們必須建立文件索引并對其進行搜索,然后在其中進行搜索操作。
這是示例程序,注釋以內聯方式給出:
package com.wf.lucene;import java.io.File; import java.io.FileReader; import java.util.ArrayList;import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.StringField; 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.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopScoreDocCollector; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version;public class LuceneOnFileSystemExample {static String DATA_FOLDER = "/home/piyas/Documents/Winkframe/sample_text_files/drugs/"; // Where the files are.static String INDEX_FOLDER = "/home/piyas/Documents/Winkframe/sample_text_files/drugindex/"; // Where the Index files are.private static StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_46);private static IndexWriter writer;private static ArrayList<File> queue = new ArrayList<File>();public static void indexFilesAndShowResults(String dataFilePath,String indexFilePath,String searchTerm) throws Exception {// Indexing partindexOnThisPath(indexFilePath); // Function for setting the Index PathindexFileOrDirectory(dataFilePath); // Indexing the filescloseIndex(); //Function for closing the files// Search PartsearchInIndexAndShowResult(indexFilePath, searchTerm);}public static void searchInIndexAndShowResult(String indexFilePath,String searchString) throws Exception{IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(indexFilePath))); // The api call to read the indexIndexSearcher searcher = new IndexSearcher(reader); // The Index Searcher ComponentTopScoreDocCollector collector = TopScoreDocCollector.create(5, true);Query q = new QueryParser(Version.LUCENE_46, "contents", analyzer).parse(searchString);searcher.search(q, collector);ScoreDoc[] hits = collector.topDocs().scoreDocs;// display resultsSystem.out.println("Found " + hits.length + " hits.");for(int i=0;i<hits.length;++i) {int docId = hits[i].doc;Document d = searcher.doc(docId);System.out.println((i + 1) + ". " + d.get("path") + " score=" + hits[i].score); // Found the document}}public static void closeIndex() throws Exception {writer.close(); // Close the Index}public static void indexOnThisPath(String indexDir) throws Exception {// the boolean true parameter means to create a new index everytime,// potentially overwriting any existing files there.FSDirectory dir = FSDirectory.open(new File(indexDir));IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_46, analyzer);writer = new IndexWriter(dir, config);}/*** Indexes a file or directory* @param fileName the name of a text file or a folder we wish to add to the index* @throws java.io.IOException when exception*/public static void indexFileOrDirectory(String filePath) throws Exception {// Adding the files in lucene index//===================================================//gets the list of files in a folder (if user has submitted//the name of a folder)//===================================================addFiles(new File(filePath));int originalNumDocs = writer.numDocs();for (File f : queue) {FileReader fr = null;try {Document doc = new Document();//===================================================// add contents of file//===================================================fr = new FileReader(f);doc.add(new TextField("contents", fr));doc.add(new StringField("path", f.getPath(), Field.Store.YES));doc.add(new StringField("filename", f.getName(), Field.Store.YES));writer.addDocument(doc);System.out.println("Added: " + f);} catch (Exception e) {System.out.println("Could not add: " + f);} finally {fr.close();}}int newNumDocs = writer.numDocs();System.out.println("");System.out.println("************************");System.out.println((newNumDocs - originalNumDocs) + " documents added.");System.out.println("************************");queue.clear();}private static void addFiles(File file) {if (!file.exists()) {System.out.println(file + " does not exist.");}if (file.isDirectory()) {for (File f : file.listFiles()) {addFiles(f);}} else {String filename = file.getName().toLowerCase();//===================================================// Only index text files//===================================================if (filename.endsWith(".htm") || filename.endsWith(".html") ||filename.endsWith(".xml") || filename.endsWith(".txt")) {queue.add(file);} else {System.out.println("Skipped " + filename);}}}/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubtry{indexFilesAndShowResults(DATA_FOLDER,INDEX_FOLDER,"HIV"); // Indexing files and Searching the word from files.}catch(Exception e){e.printStackTrace();}}}本文隨附了示例應用程序。
我們提供索引目錄,搜索查詢字符串和最大匹配數,然后調用searchIndex方法。 在該方法中,我們創建一個IndexSearcher , QueryParser和Query對象。 請注意, QueryParser使用了我們用于使用IndexWriter創建文檔的字段的名稱(“內容”),并且再次使用了相同類型的分析器( SimpleAnalyzer )。 我們執行搜索,并為找到匹配項的每個Document提取包含文件名(“ filename”)的字段的值,然后進行打印。
在這里,我們使用Apache Lucene創建了一個簡單的搜索應用程序。 在下一篇文章中,我們將使用更高級的查詢以及Lucene索引和搜索的其他高級選項。
5.下載源代碼
您可以下載源代碼, 在這里和數據歸檔在這里 。
翻譯自: https://www.javacodegeeks.com/2015/09/lucene-components-overview.html
lucene
總結
以上是生活随笔為你收集整理的lucene_Lucene组件概述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地暖种类有哪些_地暖种类介绍
- 下一篇: 林徽因的老公是谁(林徽因与丈夫伉俪情深的