- 自己動手寫分布式搜索引擎
- 羅剛
- 1325字
- 2020-11-28 15:52:48
3.3.1 查詢過程
Lucene中使用IndexSearcher類對索引進行檢索。IndexSearcher類繼承自抽象類Searcher。查詢依賴一個或者多個索引庫,IndexSearcher依賴一個或者多個IndexReader。查詢執行過程如圖3-9所示。

圖3-9 查詢執行過程
在初始化一個IndexSearcher類時,重要的就是要告訴它使用哪個索引完成查找任務??梢杂肐ndexReader初始化一個IndexSearcher對象。
Directory directory = FSDirectory.open(new File("E:/luceneTest/fileindex")); IndexReader indexReader = DirectoryReader.open(directory); IndexSearcher indexSearcher = new IndexSearcher(indexReader);
DirectoryReader是IndexReader的子類。使用DirectoryReader.open(directory)方法得到IndexReader的實例。
Directory類型的對象包含索引存放的路徑信息,從而可以定位索引。這里使用Directory類型的對象來創建IndexReader,然后再用IndexReader構建IndexSearcher。要查詢的索引往往只有一個,所以也可以直接使用Directory類型的對象來構建IndexSearcher。
String indexDir = "D:/indexdir"; //索引庫路徑 Directory directory = FSDirectory.open(new File(indexDir)); //打開一個文件路徑 //只讀的方式使用directory,所以read-only=true IndexSearcher searcher = new IndexSearcher(directory, true); //隱式創建了 //IndexReader
上面只是一個隱式創建IndexReader的簡單寫法。使用Directory構造的IndexSearcher實例仍然各自持有一個IndexReader實例,若系統中存在同一個索引的多個IndexSearcher實例時,會占用過多的內存空間。這時,應該是一份索引用一個IndexReader實例打開,用IndexReader構造IndexSearcher實例。
可以用DirectoryReader.getVersion()取得版本號:
System.out.println("版本號 :"+reader.getVersion());
DirectoryReader類是IndexReader的子類。
把111.doc分成111,1111.doc分成1111,11111.doc分成11111。這樣輸入111,就只能搜索到111.doc。一段有意義的文字需要通過Analyzer分割成一個個詞語后才能按關鍵詞搜索。Analyzer就是分析器,StandardAnalyzer是Lucene中最常用的分析器。
Analyzer analyzer = new StandardAnalyzer();
為了達到更好的搜索效果,不同的語言可以使用不同的分析器,例如CnAnalyzer就是一個主要處理中文的分析器。
Analyzer返回的結果就是一串Token。Token包含一個代表詞本身含義的字符串和該詞在文章中相應的起止偏移位置,Token還包含一個用來存儲詞類型的字符串。
Term是搜索語法的最小單位,復雜的搜索語法會分解成一個個的Term查詢,它表示文檔中的一個詞語。Term由兩部分組成:它表示的詞語和這個詞語所出現的Field。例如:
new Term("url", "http://www.lietu.com");
最簡單的Query對象是TermQuery。根據TermQuery查詢索引庫。
Query query = new TermQuery(new Term("url", "http://www.lietu.com")); //搜索索引庫并且返回最相關的10個文檔 TopDocs tds = searcher.search(query, 10);
要是用戶輸入一個逗號,也會搜出文檔來,逗號是停用詞。一般停用詞進索引,但是搜索的時候會過濾掉。指用戶輸入逗號,系統識別為停用詞就給提示說它不能進行搜索。
查詢串中可能包括一些高級查詢語法,例如,要查找包含java的PDF文件,可以使用查詢串“java filetype:pdf”。所以用查詢分析器QueryParser來解析查詢串,也就是根據查詢串生成Query對象。例如:
Analyzer analyzer = new StandardAnalyzer(); QueryParser qp = new QueryParser(fields, analyzer); query = qp.parse(queryString);
使用IndexSearcher的search()方法執行搜索,返回一個TopDocs對象。TopDocs對象中的totalHits屬性記錄搜索返回結果的總條數?;镜年P鍵詞查詢代碼如下:
String indexDir = "D:/indexdir"; //索引庫路徑 Directory directory = FSDirectory.open(new File(indexDir)); //打開一個文件路徑 // read-only=true IndexSearcher searcher = new IndexSearcher(directory, true); //搜索 String defaultField = "title"; //默認查詢列 String queryString ="NBA"; //查詢詞 Analyzer analyzer = new StandardAnalyzer(); QueryParser parser = new QueryParser(defaultField, analyzer); Query query = parser.parse(queryString); TopDocs docs = searcher.search(query, 10); //查詢最多只返回前10條結果
這里的FSDirectory表示硬盤中的索引,RAMDirectory表示內存中的索引,可以用來測試索引和查找過程。
遍歷查詢結果:
ScoreDoc[] hits = docs.scoreDocs; //從TopDocs取得查詢結果 // 遍歷結果 for (ScoreDoc hit : hits){ Document hitDoc = searcher.doc(hit.doc); System.out.println(hitDoc.get("title") +hit.score); //輸出標題和文檔相關度分值 }
ScoreDoc中的score屬性就是相關度。相關度得分是1~0的值。1表示相關度最高,而0則表示不相關。文檔的相關度跟很多因素有關。比如字段的長短、里面詞條的權重等。決定score的因素簡單概括如下:
(1) 項頻率,即查詢項在某個文檔中出現的次數;
(2) 文檔頻率,即查詢項在很多文檔中出現的次數。
完整的查詢代碼:
Directory directory = FSDirectory.open(new File("d:/testindex")); // DirectoryReader讀入一個目錄下的索引文件 IndexReader ir = DirectoryReader.open(directory); //打開索引庫 IndexSearcher searcher = new IndexSearcher(ir); //根據查詢詞搜索索引庫 TopDocs docs = searcher.search(new TermQuery(new Term("title", "text")), 10); //遍歷查詢結果 ScoreDoc[] hits = docs.scoreDocs; for (ScoreDoc hit : hits){ System.out.print("doc:"+hit.doc+" score:"+hit.score+"\n"); } //關閉索引庫 ir.close();
- CorelDRAW X6圖形設計立體化教程
- 常用工具軟件案例教程
- 創意UI:Photoshop玩轉移動UI設計
- Drupal Multimedia
- Drools規則引擎技術指南
- Puppet權威指南
- 中文版3ds Max 2016/VRay效果圖制作技術大全
- 金融精英PPT實操手冊:世界知名公司這樣展示研究報告
- MATLAB在日常計算中的應用
- Photoshop & Illustrator平面設計火星課堂
- Photoshop后期強:多重曝光專業技法寶典
- 3ds Max-Photoshop游戲模型制作全攻略
- WS/BPEL 2.0 for SOA Composite Applications with Oracle SOA Suite 11g
- Premiere視頻編輯案例教程:Premiere Pro 2020(微課版·第2版)
- 中文版Premiere Pro 2022基礎教程