摘要:系列文章系列一快速入門系列二使用及索引文檔的基本操作系列三查詢及高亮是什么在維基百科的定義是一套用于全文檢索和搜索的開放源代碼程序庫,由軟件基金會(huì)支持和提供。全面準(zhǔn)確和快速是衡量全文檢索系統(tǒng)的關(guān)鍵指標(biāo)。結(jié)果列表有相關(guān)度排序。
系列文章:
Lucene系列(一)快速入門
Lucene系列(二)luke使用及索引文檔的基本操作
Lucene系列(三)查詢及高亮
Lucene是什么?Lucene在維基百科的定義
Lucene是一套用于全文檢索和搜索的開放源代碼程序庫,由Apache軟件基金會(huì)支持和提供。Lucene提供了一個(gè)簡單卻強(qiáng)大的應(yīng)用程序接口,能夠做全文索引和搜索,在Java開發(fā)環(huán)境里L(fēng)ucene是一個(gè)成熟的免費(fèi)開放源代碼工具;就其本身而論,Lucene是現(xiàn)在并且是這幾年,最受歡迎的免費(fèi)Java信息檢索程序庫。
另外,Lucene不提供爬蟲功能,如果需要獲取內(nèi)容需要自己建立爬蟲應(yīng)用。
Lucene只做索引和搜索工作。
Lucene官網(wǎng)
http://lucene.apache.org/
打開Luncene官網(wǎng)你會(huì)發(fā)現(xiàn)Lucene版本更新的太快了,現(xiàn)在最新的版本已經(jīng)是7.2.1。不過這也變相說明了Luncene這個(gè)開源庫的火爆。
Lucene和solr
我想提到Lucene,不得不提solr了。
很多剛接觸Lucene和Solr的人都會(huì)問這個(gè)明顯的問題:我應(yīng)該使用Lucene還是Solr?
答案很簡單:如果你問自己這個(gè)問題,在99%的情況下,你想使用的是Solr. 形象的來說Solr和Lucene之間關(guān)系的方式是汽車及其引擎。 你不能駕駛一臺(tái)發(fā)動(dòng)機(jī),但可以開一輛汽車。 同樣,Lucene是一個(gè)程序化庫,您不能按原樣使用,而Solr是一個(gè)完整的應(yīng)用程序,您可以立即使用它。(參考:Lucene vs Solr)
全文檢索是什么?全文檢索在百度百科的定義
全文數(shù)據(jù)庫是全文檢索系統(tǒng)的主要構(gòu)成部分。所謂全文數(shù)據(jù)庫是將一個(gè)完整的信息源的全部內(nèi)容轉(zhuǎn)化為計(jì)算機(jī)可以識(shí)別、處理的信息單元而形成的數(shù)據(jù)集合。全文數(shù)據(jù)庫不僅存儲(chǔ)了信息,而且還有對(duì)全文數(shù)據(jù)進(jìn)行詞、字、段落等更深層次的編輯、加工的功能,而且所有全文數(shù)據(jù)庫無一不是海量信息數(shù)據(jù)庫。
全文檢索首先將要查詢的目標(biāo)文檔中的詞提取出來,組成索引,通過查詢索引達(dá)到搜索目標(biāo)文檔的目的。這種先建立索引,再對(duì)索引進(jìn)行搜索的過程就叫全文檢索(Full-text Search)。
全文檢索(Full-Text Retrieval)是指以文本作為檢索對(duì)象,找出含有指定詞匯的文本。
全面、準(zhǔn)確和快速是衡量全文檢索系統(tǒng)的關(guān)鍵指標(biāo)。
關(guān)于全文檢索,我們要知道:
只處理文本。
不處理語義。
搜索時(shí)英文不區(qū)分大小寫。
結(jié)果列表有相關(guān)度排序。(查出的結(jié)果如果沒有相關(guān)度排序,那么系統(tǒng)不知道我想要的結(jié)果在哪一頁。我們?cè)谑褂冒俣人阉鲿r(shí),一般不需要翻頁,為什么?因?yàn)榘俣茸隽讼嚓P(guān)度排序:為每一條結(jié)果打一個(gè)分?jǐn)?shù),這條結(jié)果越符合搜索條件,得分就越高,叫做相關(guān)度得分,結(jié)果列表會(huì)按照這個(gè)分?jǐn)?shù)由高到低排列,所以第1頁的結(jié)果就是我們最想要的結(jié)果。)
在信息檢索工具中,全文檢索是最具通用性和實(shí)用性的。
參考:https://zhuanlan.zhihu.com/p/...
全文檢索和數(shù)據(jù)庫搜索的區(qū)別
簡單來說,這兩者解決的問題是不一樣。數(shù)據(jù)庫搜索在匹配效果、速度、效率等方面都遜色于全文檢索。下面我們的一個(gè)例子就能很清楚說明這一點(diǎn)。Lucene實(shí)現(xiàn)全文檢索流程是什么?
全文檢索的流程分為兩大部分:索引流程、搜索流程。
索引流程:即采集數(shù)據(jù)構(gòu)建文檔對(duì)象分析文檔(分詞)創(chuàng)建索引。
搜索流程:即用戶通過搜索界面創(chuàng)建查詢執(zhí)行搜索,搜索器從索引庫搜索渲染搜索結(jié)果
我們?cè)谙旅娴囊粋€(gè)程序中,對(duì)這個(gè)全文檢索的流程會(huì)有進(jìn)一步的了解。
Lucene實(shí)現(xiàn)向文檔寫索引并讀取文檔截止2018/3/30,用到的jar包結(jié)為最新。
程序用到的數(shù)據(jù)下載地址:
鏈接:https://pan.baidu.com/s/1ccgrCCRBBGOL-fmmOLrxlQ
密碼:vyof
創(chuàng)建Maven項(xiàng)目,并添加相關(guān)jar包依賴
org.apache.lucene lucene-core 7.2.1 org.apache.lucene lucene-queryparser 7.2.1 org.apache.lucene lucene-analyzers-common 7.2.1
向文檔里寫索引
package lucene_demo1; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.nio.file.Paths; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; /** * *TODO 索引文件 * @author Snaiclimb * @date 2018年3月30日 * @version 1.8 */ public class Indexer { // 寫索引實(shí)例 private IndexWriter writer; /** * 構(gòu)造方法 實(shí)例化IndexWriter * * @param indexDir * @throws IOException */ public Indexer(String indexDir) throws IOException { //得到索引所在目錄的路徑 Directory directory = FSDirectory.open(Paths.get(indexDir)); // 標(biāo)準(zhǔn)分詞器 Analyzer analyzer = new StandardAnalyzer(); //保存用于創(chuàng)建IndexWriter的所有配置。 IndexWriterConfig iwConfig = new IndexWriterConfig(analyzer); //實(shí)例化IndexWriter writer = new IndexWriter(directory, iwConfig); } /** * 關(guān)閉寫索引 * * @throws Exception * @return 索引了多少個(gè)文件 */ public void close() throws IOException { writer.close(); } public int index(String dataDir) throws Exception { File[] files = new File(dataDir).listFiles(); for (File file : files) { //索引指定文件 indexFile(file); } //返回索引了多少個(gè)文件 return writer.numDocs(); } /** * 索引指定文件 * * @param f */ private void indexFile(File f) throws Exception { //輸出索引文件的路徑 System.out.println("索引文件:" + f.getCanonicalPath()); //獲取文檔,文檔里再設(shè)置每個(gè)字段 Document doc = getDocument(f); //開始寫入,就是把文檔寫進(jìn)了索引文件里去了; writer.addDocument(doc); } /** * 獲取文檔,文檔里再設(shè)置每個(gè)字段 * * @param f * @return document */ private Document getDocument(File f) throws Exception { Document doc = new Document(); //把設(shè)置好的索引加到Document里,以便在確定被索引文檔 doc.add(new TextField("contents", new FileReader(f))); //Field.Store.YES:把文件名存索引文件里,為NO就說明不需要加到索引文件里去 doc.add(new TextField("fileName", f.getName(), Field.Store.YES)); //把完整路徑存在索引文件里 doc.add(new TextField("fullPath", f.getCanonicalPath(), Field.Store.YES)); return doc; } public static void main(String[] args) { //索引指定的文檔路徑 String indexDir = "D:lucenedataindex"; ////被索引數(shù)據(jù)的路徑 String dataDir = "D:lucenedata"; Indexer indexer = null; int numIndexed = 0; //索引開始時(shí)間 long start = System.currentTimeMillis(); try { indexer = new Indexer(indexDir); numIndexed = indexer.index(dataDir); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { indexer.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //索引結(jié)束時(shí)間 long end = System.currentTimeMillis(); System.out.println("索引:" + numIndexed + " 個(gè)文件 花費(fèi)了" + (end - start) + " 毫秒"); } }
運(yùn)行效果:
我們查看D:lucenedataindex文件夾。我們發(fā)現(xiàn)多了一些東西,這些東西就是我們馬上用來全文搜索的索引。
//索引指定的文檔路徑 String indexDir = "D:lucenedataindex";
Mark博文:Lucene的索引文件格式(1)
全文檢索測試
package lucene_demo1; import java.nio.file.Paths; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; 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.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; /** * 根據(jù)索引搜索 *TODO * @author Snaiclimb * @date 2018年3月25日 * @version 1.8 */ public class Searcher { public static void search(String indexDir, String q) throws Exception { // 得到讀取索引文件的路徑 Directory dir = FSDirectory.open(Paths.get(indexDir)); // 通過dir得到的路徑下的所有的文件 IndexReader reader = DirectoryReader.open(dir); // 建立索引查詢器 IndexSearcher is = new IndexSearcher(reader); // 實(shí)例化分析器 Analyzer analyzer = new StandardAnalyzer(); // 建立查詢解析器 /** * 第一個(gè)參數(shù)是要查詢的字段; 第二個(gè)參數(shù)是分析器Analyzer */ QueryParser parser = new QueryParser("contents", analyzer); // 根據(jù)傳進(jìn)來的p查找 Query query = parser.parse(q); // 計(jì)算索引開始時(shí)間 long start = System.currentTimeMillis(); // 開始查詢 /** * 第一個(gè)參數(shù)是通過傳過來的參數(shù)來查找得到的query; 第二個(gè)參數(shù)是要出查詢的行數(shù) */ TopDocs hits = is.search(query, 10); // 計(jì)算索引結(jié)束時(shí)間 long end = System.currentTimeMillis(); System.out.println("匹配 " + q + " ,總共花費(fèi)" + (end - start) + "毫秒" + "查詢到" + hits.totalHits + "個(gè)記錄"); // 遍歷hits.scoreDocs,得到scoreDoc /** * ScoreDoc:得分文檔,即得到文檔 scoreDocs:代表的是topDocs這個(gè)文檔數(shù)組 * * @throws Exception */ for (ScoreDoc scoreDoc : hits.scoreDocs) { Document doc = is.doc(scoreDoc.doc); System.out.println(doc.get("fullPath")); } // 關(guān)閉reader reader.close(); } public static void main(String[] args) { String indexDir = "D:lucenedataindex"; //我們要搜索的內(nèi)容 String q = "Jean-Philippe sdsds Barrette-LaPierre"; try { search(indexDir, q); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
上面我們搜索的是:"Jean-Philippe Barrette-LaPierre";即使你:"Jean-Philippe ssss Barrette-LaPierre"這樣搜索也還是搜索到,以為Lucene對(duì)其進(jìn)行了分詞,對(duì)中文無效。
我們剛剛實(shí)現(xiàn)的程序已經(jīng)清楚地向我們展示了Lucene實(shí)現(xiàn)全文檢索流程,我們?cè)賮砘仡櫼幌隆?br>
在Lucene中,采集數(shù)據(jù)(從網(wǎng)站爬取或連接數(shù)據(jù)庫)就是為了創(chuàng)建索引,創(chuàng)建索引需要先將采集的原始數(shù)據(jù)加工為文檔,再由文檔分詞產(chǎn)生索引。文檔(Document) 中包含若干個(gè)Field域。
IndexWriter是索引過程的核心組件,通過IndexWriter可以創(chuàng)建新索引、更新索引、刪除索引操作。IndexWriter需要通過Directory對(duì)索引進(jìn)行存儲(chǔ)操作。
Directory描述了索引的存儲(chǔ)位置,底層封裝了I/O操作,負(fù)責(zé)對(duì)索引進(jìn)行存儲(chǔ)。它是一個(gè)抽象類,它的子類常用的包括FSDirectory(在文件系統(tǒng)存儲(chǔ)索引)、RAMDirectory(在內(nèi)存存儲(chǔ)索引)。
在對(duì)Docuemnt中的內(nèi)容索引之前需要使用分詞器進(jìn)行分詞 ,分詞的主要過程就是分詞、過濾兩步。 分詞就是將采集到的文檔內(nèi)容切分成一個(gè)一個(gè)的詞,具體應(yīng)該說是將Document中Field的value值切分成一個(gè)一個(gè)的詞。
過濾包括去除標(biāo)點(diǎn)符號(hào)、去除停用詞(的、是、a、an、the等)、大寫轉(zhuǎn)小寫、詞的形還原(復(fù)數(shù)形式轉(zhuǎn)成單數(shù)形參、過去式轉(zhuǎn)成現(xiàn)在式等)。
停用詞是為節(jié)省存儲(chǔ)空間和提高搜索效率,搜索引擎在索引頁面或處理搜索請(qǐng)求時(shí)會(huì)自動(dòng)忽略某些字或詞,這些字或詞即被稱為Stop Words(停用詞)。比如語氣助詞、副詞、介詞、連接詞等,通常自身并無明確的意義,只有將其放入一個(gè)完整的句子中才有一定作用,如常見的“的”、“在”、“是”、“啊”等。
Lucene中自帶了StandardAnalyzer,它可以對(duì)英文進(jìn)行分詞。
參照:https://zhuanlan.zhihu.com/p/...
Lucene工作原理總結(jié)1、索引流程
從原始文件中提取一些可以用來搜索的數(shù)據(jù)(封裝成各種Field),把各field再封裝成document,然后對(duì)document進(jìn)行分析(對(duì)各字段分詞),得到一些索引目錄寫入索引庫,document本身也會(huì)被寫入一個(gè)文檔信息庫;
2、搜索流程
根據(jù)關(guān)鍵詞解析(queryParser)出查詢條件query(Termquery),利用搜索工具(indexSearcher)去索引庫獲取文檔id,然后再根據(jù)文檔id去文檔信息庫獲取文檔信息
分詞器不同,建立的索引數(shù)據(jù)就不同;比較通用的一個(gè)中文分詞器IKAnalyzer的用法
3、相關(guān)度得分
a) 在建立索引的時(shí)候,可以給指定文檔的指定域設(shè)置一個(gè)權(quán)重
Field.setBoosts()(現(xiàn)在5.5版本之前的是這樣設(shè)置權(quán)重,后面的不是了)
b) 在搜索的時(shí)候,可以給不同的搜索域設(shè)置不同的權(quán)重
Boosts = new HashMap
MultiFieldsQueryParser(fields,analyzer,boosts)
歡迎關(guān)注我的微信公眾號(hào):“Java面試通關(guān)手冊(cè)”(堅(jiān)持原創(chuàng),分享美文,分享各種Java學(xué)習(xí)資源,面試題,以及企業(yè)級(jí)Java實(shí)戰(zhàn)項(xiàng)目回復(fù)關(guān)鍵字免費(fèi)領(lǐng)取):
Lucene我想暫時(shí)先更新到這里,僅僅這三篇文章想掌握Lucene是遠(yuǎn)遠(yuǎn)不夠的。另外我這里三篇文章都用的最新的jar包,Lucene更新太快,5系列后的版本和之前的有些地方還是有挺大差距的,就比如為文檔域設(shè)置權(quán)值的setBoost方法6.6以后已經(jīng)被廢除了等等。因?yàn)闀r(shí)間有限,所以我就草草的看了一下Lucene的官方文檔,大多數(shù)內(nèi)容還是看java1234網(wǎng)站的這個(gè)視頻來學(xué)習(xí)的,然后在版本和部分代碼上做了改進(jìn)。截止2018/4/1,上述代碼所用的jar包皆為最新。
最后推薦一下自己覺得還不錯(cuò)的Lucene學(xué)習(xí)網(wǎng)站/博客:
官方網(wǎng)站:Welcome to Apache Lucene
Github:Apache Lucene and Solr
Lucene專欄
搜索系統(tǒng)18:lucene索引文件結(jié)構(gòu)
Lucene6.6的介紹和使用
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/68951.html
摘要:系列文章系列一快速入門系列二使用及索引文檔的基本操作系列三查詢及高亮入門簡介地址下載地址是一個(gè)用于搜索引擎的,方便開發(fā)和診斷的可視化工具。使用作為其最低級(jí)別的搜索引擎基礎(chǔ)。截止,上述代碼所用的包皆為最新。 系列文章: Lucene系列(一)快速入門 Lucene系列(二)luke使用及索引文檔的基本操作 Lucene系列(三)查詢及高亮 luke入門 簡介: github地址:http...
摘要:極速的查詢速度通過有限狀態(tài)轉(zhuǎn)換器實(shí)現(xiàn)了用于全文檢索的倒排索引,實(shí)現(xiàn)了用于存儲(chǔ)數(shù)值數(shù)據(jù)和地理位置數(shù)據(jù)的樹,以及用于分析的列存儲(chǔ)。每個(gè)數(shù)據(jù)都被編入了索引。強(qiáng)大的彈性保障硬件故障。檢測這些故障并確保集群和數(shù)據(jù)的安全性和可用性。 What —— Elasticsearch是什么? Elasticsearch是一個(gè)基于Lucene的搜索服務(wù)器,Elasticsearch也是使用Java編寫的,它...
摘要:那我們現(xiàn)在是不知道記錄是否真真正正存儲(chǔ)到索引庫中的,因?yàn)槲覀兛床灰姟K饕龓齑娣诺臄?shù)據(jù)放在文件下,我們也是不能打開文件的。 什么是Lucene?? Lucene是apache軟件基金會(huì)發(fā)布的一個(gè)開放源代碼的全文檢索引擎工具包,由資深全文檢索專家Doug Cutting所撰寫,它是一個(gè)全文檢索引擎的架構(gòu),提供了完整的創(chuàng)建索引和查詢索引,以及部分文本分析的引擎,Lucene的目的是為軟件開發(fā)...
閱讀 2452·2021-11-22 09:34
閱讀 3063·2021-10-25 09:43
閱讀 1975·2021-10-11 10:59
閱讀 3361·2021-09-22 15:13
閱讀 2323·2021-09-04 16:40
閱讀 418·2019-08-30 15:53
閱讀 3186·2019-08-30 11:13
閱讀 2602·2019-08-29 17:30