自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

關(guān)于Lucene以及索引和搜索的流程

開發(fā) 后端
Lucene的普及和成功的背后是因?yàn)樗暮唵巍R虼?,你不需要深入理解Lucene的信息索引和檢索工作方面的知識就可以開始使用。Lucene提供了簡單但是強(qiáng)大的核心API去實(shí)現(xiàn)全文索引和檢索,你只需要掌握少數(shù)的類就能將Lucene整合到應(yīng)用中。

Lucene的普及和成功的背后是因?yàn)樗暮唵巍?/p>

因此,你不需要深入理解Lucene的信息索引和檢索工作方面的知識就可以開始使用。

Lucene提供了簡單但是強(qiáng)大的核心API去實(shí)現(xiàn)全文索引和檢索,你只需要掌握少數(shù)的類就能將Lucene整合到應(yīng)用中。

剛接觸Lucene的人可能會誤認(rèn)為Lucene是一個文件搜索工具、網(wǎng)絡(luò)爬蟲、或者網(wǎng)頁搜索引擎。實(shí)際上Lucene是一個軟件庫,而不是一個全功能的搜索應(yīng)用程序。它涉及全文索引和搜索,而且做得非常好。Lucene可以讓你的應(yīng)用程序隱藏起復(fù)雜的索引和搜索背后的操作,而使用簡單的API處理特定的問題領(lǐng)域和業(yè)務(wù)規(guī)則。你可以想象Lucene就是像一個層,你的應(yīng)用就在層的上面。

Lucene允許你添加索引和搜索功能到應(yīng)用程序中。Lucene不關(guān)心數(shù)據(jù)的來源,Lucene可以索引和搜索任何可以轉(zhuǎn)換成文本格式的數(shù)據(jù)。這意味著你可以用Lucene索引和搜索數(shù)據(jù):遠(yuǎn)程web服務(wù)器上的網(wǎng)頁、存儲在本地文件系統(tǒng)的文檔、簡單的文本文件、Microsoft Word文檔、HTML或PDF文件,或者其他任何可以從中提取文本信息的格式文件。

所有搜索引擎的核心就是索引的概念:把原始數(shù)據(jù)處理成一個高效的交叉引用查找,以便快速檢索。讓我們看看快速高效的索引和搜索過程。

1.索引是什么,為什么它這么重要?

假如你需要搜索大量的文件,你希望找到那些包含某個單詞或詞組的文件。你將如何去寫一個程序?qū)崿F(xiàn)這個功能?一個做法就是按順序掃描每一個文件,搜索是否包含給定的單詞或詞組。但是這樣的做法有很多缺陷的,其中最明顯的就是在大量的文件存在的情況下,速度是令人無法接受的。這種情況下,索引產(chǎn)生了。為了搜索大量的文本,你首先要對這些文本以特定的結(jié)構(gòu)存儲,這種存儲結(jié)構(gòu)可以讓你迅速的搜索,消除慢的順序掃描的過程。這種存儲結(jié)構(gòu)就叫索引,將文本轉(zhuǎn)換成特定結(jié)構(gòu)存儲的過程,就叫建立索引。

索引作為一種數(shù)據(jù)結(jié)構(gòu),允許你快速隨機(jī)的訪問存儲在里面的詞。類似于字典的目錄,某個詞對應(yīng)到某一頁,查找的時候直接定位到那一頁,速度就非常快,不用一頁一頁的翻去查找。Lucene的索引是一種專門設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu),通常作為一組索引文件存儲在文件系統(tǒng)上。

2.什么是搜索?

在索引中搜索關(guān)鍵詞,找到包含關(guān)鍵詞的文檔的過程就是搜索。搜索質(zhì)量通常使用準(zhǔn)確度和召回率來描述。所謂召回率是指一次搜索結(jié)果集合中符合用戶要求的數(shù)目與和用戶查詢相關(guān)的總數(shù)之比,而準(zhǔn)確率是指一次搜索結(jié)果集合中符合用戶要求的數(shù)目與該次搜索結(jié)果總數(shù)之比。我們也需要考慮其他有關(guān)搜索的因素,比如速度和快速搜索大量文本的能力,單個和多項(xiàng)查詢、 短語查詢、 通配符、 結(jié)果的排名和排序的支持也很重要。

3.Lucene in Action

假如我們需要索引和搜索存儲在一個目錄下的文件。

在我們使用Lucene進(jìn)行搜索之前,我們需要先建立索引。使用的Lucene的版本是3.6。

3.1建立索引

1)創(chuàng)建存放索引的目錄Directory

2)創(chuàng)建索引器配置管理類IndexWriterConfig

3)使用索引目錄和配置管理類創(chuàng)建索引器

4)使用索引器將Document寫到索引文件中

索引器類:

  1. /**  
  2.  * 索引器  
  3.  * @author Luxh  
  4.  */ 
  5. public class Indexer {  
  6.        
  7.        
  8.     /**  
  9.      * 建立索引  
  10.      * @param filePath 需要建立索引的文件的存放路徑  
  11.      * @throws IOException  
  12.      */ 
  13.     public static void createIndex(String filePath) throws IOException {  
  14.            
  15.         //在當(dāng)前路徑下創(chuàng)建一個叫indexDir的目錄  
  16.         File indexDir = new File("./indexDir");  
  17.            
  18.         //創(chuàng)建索引目錄  
  19.         Directory directory = FSDirectory.open(indexDir);  
  20.            
  21.         //創(chuàng)建一個分詞器  
  22.         Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);  
  23.            
  24.         //創(chuàng)建索引配置器  
  25.         IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,analyzer);  
  26.            
  27.            
  28.         LogMergePolicy mergePolicy = new LogByteSizeMergePolicy();  
  29.            
  30.         //設(shè)置segment添加文檔(Document)時的合并頻率  
  31.         //值較小,建立索引的速度就較慢  
  32.         //值較大,建立索引的速度就較快,>10適合批量建立索引  
  33.         mergePolicy.setMergeFactor(50);  
  34.            
  35.         //設(shè)置segment最大合并文檔(Document)數(shù)  
  36.         //值較小有利于追加索引的速度  
  37.         //值較大,適合批量建立索引和更快的搜索  
  38.         mergePolicy.setMaxMergeDocs(5000);  
  39.            
  40.         //啟用復(fù)合式索引文件格式,合并多個segment  
  41.         mergePolicy.setUseCompoundFile(true);  
  42.            
  43.            
  44.         indexWriterConfig.setMergePolicy(mergePolicy);  
  45.            
  46.         //設(shè)置索引的打開模式  
  47.         indexWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);  
  48.            
  49.         //創(chuàng)建索引器  
  50.         IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);  
  51.            
  52.            
  53.         File fileDir = new File(filePath);  
  54.         for(File file : fileDir.listFiles()) {  
  55.             //Document是Lucene的文檔結(jié)構(gòu),需要索引的對象都要轉(zhuǎn)換為Document  
  56.             Document document = new Document();  
  57.                
  58.             //文件名,可查詢,分詞,存儲到索引庫記錄中  
  59.             document.add(new Field("name",getFileName(file),Store.YES,Index.ANALYZED));  
  60.                
  61.             //文件路徑,可查詢,不分詞,存儲到索引庫記錄中  
  62.             document.add(new Field("path",file.getAbsolutePath(),Store.YES,Index.NOT_ANALYZED));  
  63.                
  64.             //大文本內(nèi)容,可查詢,不存儲,實(shí)際上可根據(jù)文件路徑去找到真正的文本內(nèi)容  
  65.             //document.add(new Field("content",new FileReader(file)));  
  66.                
  67.             //小文本內(nèi)容,可以存儲到索引記錄庫  
  68.             document.add(new Field("content",getFileContent(file),Store.YES,Index.ANALYZED));  
  69.                
  70.             //把文檔添加到索引庫  
  71.             indexWriter.addDocument(document);  
  72.                
  73.         }  
  74.            
  75.         //提交索引到磁盤上的索引庫,關(guān)閉索引器  
  76.         indexWriter.close();  
  77.    
  78.     }  
  79.        
  80.     /**  
  81.      * 獲取文件名  
  82.      */ 
  83.     public static String getFileName(File file) {  
  84.         String fileName = "";  
  85.         if(file != null) {  
  86.             fileName = file.getName().substring(0, file.getName().lastIndexOf("."));  
  87.         }  
  88.         return fileName;  
  89.     }  
  90.        
  91.     /**  
  92.      * 獲取文本  
  93.      * @param file  
  94.      */ 
  95.     public static String getFileContent(File file) {  
  96.         FileReader fr = null;  
  97.         BufferedReader br = null;  
  98.         String content = "";  
  99.         try {  
  100.             fr = new FileReader(file);  
  101.             br = new BufferedReader(fr);  
  102.             StringBuffer sb = new StringBuffer();  
  103.             String line = br.readLine();  
  104.             while(null != line){  
  105.                 sb.append(line);  
  106.                 line = br.readLine();  
  107.             }  
  108.             content = sb.toString();  
  109.         }catch(Exception e) {  
  110.             e.printStackTrace();  
  111.         }finally {  
  112.             try {  
  113.                 if(fr != null)  
  114.                     fr.close();  
  115.                 if(br != null)  
  116.                     br.close();  
  117.             } catch (IOException e) {  
  118.                 e.printStackTrace();  
  119.             }  
  120.         }  
  121.         return content;  
  122.            
  123.     }  
  124.    
  125.        

IndexWriter:索引器,負(fù)責(zé)創(chuàng)建和維護(hù)一條索引。

在Lucene3.6版本,只推薦使用一個構(gòu)造方法IndexWriter(Directory d,IndexWriterConfig conf),其他的構(gòu)造方法都已經(jīng)過時。所有關(guān)于IndexWriter的配置都是通過IndexWriterConfig來進(jìn)行管理。

IndexWriterConfig:索引器配置類,管理所有有關(guān)索引器的配置。只有一個構(gòu)造方法IndexWriterConfig(Version matchVersion,Analyzer analyzer),構(gòu)造方法中的參數(shù)matchVersion是Lucene的版本,analyzer是分詞器。

接下來我們運(yùn)行索引器創(chuàng)建索引。

  1. public class TestIndexer {  
  2.        
  3.     /**  
  4.      * 創(chuàng)建索引  
  5.      * @throws IOException  
  6.      */ 
  7.     @Test 
  8.     public void testCreateIndex() throws IOException{  
  9.         //存放需要建立索引的文件的目錄路徑  
  10.         String filePath = "./fileDir";  
  11.         //調(diào)用索引器的創(chuàng)建索引方法  
  12.         Indexer.createIndex(filePath);  
  13.     }  

這樣我們就對當(dāng)前路徑下fileDir中的文件創(chuàng)建了索引。

3.2執(zhí)行搜索

在Lucene中搜索像建立索引一樣簡單、快速。現(xiàn)在,我們建立一個搜索器,搜索包含特定文本的文件。

1)使用QueryParser將查詢的關(guān)鍵詞解析成Lucene的查詢對象Query。創(chuàng)建QueryParser的時候我們需要用到分詞器,這個分詞器要和前面創(chuàng)建索引的時候使用的分詞器一致。

2)使用FSDirectory打開索引所在的目錄。

3)使用IndexReader讀取索引目錄和使用IndexSearcher進(jìn)行搜索。

4)返回搜索結(jié)果對象TopDocs。TopDocs包含搜索到結(jié)果總數(shù)和結(jié)果的集合ScoreDocs數(shù)組

5)遍歷結(jié)果的集合ScoreDocs數(shù)組,根據(jù)每一個ScoreDoc的文檔編號獲取Document

看看搜索器的代碼:

  1. /**  
  2.  * 搜索器  
  3.  * @author Luxh  
  4.  */ 
  5. public class Searcher {  
  6.        
  7.     /**  
  8.      * 搜索  
  9.      * @param keyWord 搜索的關(guān)鍵詞  
  10.      * @param indexDir  索引目錄所在路徑  
  11.      * @throws ParseException  
  12.      * @throws IOException  
  13.      * @return List<Document>  
  14.      */ 
  15.     public static List<Document> search(String keyWord,String indexDirPath) throws ParseException, IOException {  
  16.            
  17.         String[] fields = {"name","content"};  
  18.            
  19.         //創(chuàng)建一個分詞器,和創(chuàng)建索引時用的分詞器要一致  
  20.         Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);  
  21.            
  22.         //創(chuàng)建查詢解析器  
  23.         QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_36,fields,analyzer);  
  24.            
  25.         //將查詢關(guān)鍵詞解析成Lucene的Query對象  
  26.         Query query = queryParser.parse(keyWord);  
  27.            
  28.         //打開索引目錄  
  29.         File indexDir = new File(indexDirPath);  
  30.         Directory directory = FSDirectory.open(indexDir);  
  31.            
  32.         //獲取訪問索引的接口,進(jìn)行搜索  
  33.         IndexReader indexReader  = IndexReader.open(directory);  
  34.         IndexSearcher indexSearcher = new IndexSearcher(indexReader);  
  35.            
  36.         //TopDocs 搜索返回的結(jié)果  
  37.         TopDocs topDocs = indexSearcher.search(query, 100);//只返回前100條記錄  
  38.            
  39.         int totalCount = topDocs.totalHits; // 搜索結(jié)果總數(shù)量  
  40.         System.out.println("搜索到的結(jié)果總數(shù)量為:" + totalCount);  
  41.            
  42.         ScoreDoc[] scoreDocs = topDocs.scoreDocs; // 搜索的結(jié)果集合  
  43.            
  44.         List<Document> docs = new ArrayList<Document>();  
  45.            
  46.         for(ScoreDoc scoreDoc : scoreDocs) {  
  47.             //文檔編號  
  48.             int docID = scoreDoc.doc;  
  49.             //根據(jù)文檔編號獲取文檔  
  50.             Document doc = indexSearcher.doc(docID);  
  51.             docs.add(doc);  
  52.         }  
  53.         indexReader.close();  
  54.         indexSearcher.close();  
  55.         return docs;  
  56.     }  

接下來我們運(yùn)行搜索器:

  1. public class TestSearcher {  
  2.        
  3.     /**  
  4.      * 搜索  
  5.      */ 
  6.     @Test 
  7.     public void testSearch() throws IOException, ParseException{  
  8.         //搜索關(guān)鍵詞  
  9.         String keyWord = "Java";  
  10.         //索引目錄路徑  
  11.         String indexDirPath = "./indexDir";  
  12.         //調(diào)用搜索器進(jìn)行搜索  
  13.         List<Document> docs = Searcher.search(keyWord, indexDirPath);  
  14.         for(Document doc : docs) {  
  15.             System.out.println("文件名 : "+doc.get("name"));  
  16.             System.out.println("路徑 : "+doc.get("path"));  
  17.             System.out.println("內(nèi)容 : "+doc.get("content"));  
  18.         }  
  19.     }  
  20.        
  21.        

如果有包含關(guān)鍵詞的文件,就會被搜索出來了。

原文鏈接:http://www.cnblogs.com/luxh/archive/2012/06/20/2554095.html

責(zé)任編輯:林師授 來源: 博客園
相關(guān)推薦

2011-09-16 15:55:09

Java

2012-04-13 09:05:41

LuceneJava

2017-09-15 16:00:48

Lucene存儲讀取技術(shù)

2011-06-20 18:23:06

SEO

2017-09-22 09:20:06

數(shù)據(jù)庫索引

2015-07-31 10:30:47

IBM Cloudan開源搜索

2017-09-04 16:03:46

MySQLMySQL索引索引

2009-09-22 16:23:52

搜索引擎

2024-04-16 09:53:56

PostgreSQL數(shù)據(jù)庫優(yōu)化索引

2016-10-25 12:39:37

Windows優(yōu)化桌面

2011-12-08 10:39:29

JavaLucene

2021-07-15 10:11:56

IT流程設(shè)計(jì)流程流程文化

2021-01-28 05:13:17

Oracle索引外鍵

2020-02-25 15:47:05

ElasticsearLucene地方

2024-09-04 15:54:43

Python列表索引

2013-05-24 09:57:28

搜索流程搜索產(chǎn)品設(shè)計(jì)搜索設(shè)計(jì)

2009-02-19 09:41:36

搜索引擎搜狐百度

2017-08-07 08:15:31

搜索引擎倒排

2010-02-06 15:06:14

2022-10-14 07:42:50

LuceneHTTPWeb
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號