1. 程式人生 > >Lucene學習筆記之(一)簡介和向文件寫索引並讀取文件

Lucene學習筆記之(一)簡介和向文件寫索引並讀取文件

什麼是lucene?

lucene就是一個全文檢索的工具包。

Lucene的能幹什麼?

1.      獲取內容(Acquire Content)
Lucene不提供爬蟲功能,如果需要獲取內容需要自己建立爬蟲應用。
Lucene只做索引和搜尋工作。

2.建立文件(Build Document)
文件通常由一個個域(fields)組成,例如:標題,正文,摘要等。
需要保證文件的格式一致(如都為txt格式)
在此過程中可以通過語義分析來使要儲存的文件更加精煉,也可以通過加權值來決定域和文件是否重要。
可以再建立索引的時候加權值,也可以在搜尋的時候加權值。

3.分析文件(Analyze Document)
解決如果控制符合單詞,解決拼寫錯誤,是否關聯同義詞,是否摺疊單數複數形式。
是否保留結果的偏差,當非拉丁語表示的語言,如何辨別詞。

4.建立文件索引(Index Document)

5.搜尋
支援單個或者符合查詢,短語查詢,萬用字元,模糊查詢,結果排序
支援對錯誤拼寫矯正等

6建立查詢(Build Query)

7.檢索查詢(Search Query)

8返回結果(Rednder Results)

Lucene的分詞器?

常用分詞器介紹

WhitespaceAnalyzer

僅僅是去掉了空格,沒有其他任何操作,不支援中文。

SimpleAnalyzer

講除了字母以外的符號全部去除,並且講所有字元變為小寫,需要注意的是這個分詞器同樣把資料也去除了,同樣不支援中文。

StopAnalyzer

這個和SimpleAnalyzer類似,不過比他增加了一個的是,在其基礎上還去除了所謂的stop words,比如the, a, this這些。這個也是不支援中文的。

StandardAnalyzer           

英文方面的處理和StopAnalyzer一樣的,對中文支援,使用的是單字切割。

CJKAnalyzer

這個支援中日韓,前三個字母也就是這三個國家的縮寫。這個對於中文基本上不怎麼用吧,對中文的支援很爛,它是用每兩個字作為分割,分割方式個人感覺比較奇葩,我會在下面比較舉例。

SmartChineseAnalyzer

中文的分詞。比較標準的中文分詞,對一些搜尋處理的並不是很好

步驟一:開啟eclipse,建立maven現目

步驟二:配置pom.xml檔案,程式碼如下:

        <pre name="code" class="java">                <!-- junit包
			因為是java程式,,需要用到@Test,這就是他的jar包下載。-->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>

		<!-- lucene核心包 
			以下這三個是用在lucene的全部jar包,core是核心包,queryparser是查詢jar包。
			查詢被索引檔案如果是全英文的情況下,pom.xml檔案寫這三個,就歐了!-->
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-core</artifactId>
			<version>5.3.1</version>
		</dependency>

		<!-- 查詢解析器 -->
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-queryparser</artifactId>
			<version>5.3.1</version>
		</dependency>

		<!-- 分析器 -->
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-analyzers-common</artifactId>
			<version>5.3.1</version>
		</dependency>
		<!-- 很明顯,這個是查詢被檢索檔案為全中文的情況下,
			加上以上的三個,再加上這兩個就行了。
			值得提一下,“高亮顯示”的jar包可加可不加,
			在這裡面加上,是因為這個在後面會用到。
			但是還是建議大家把這個加上,懂得多也不是個錯。
		 	-->
		<!-- 中文分詞查詢器smartcn -->
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-analyzers-smartcn</artifactId>
			<version>5.3.1</version>
		</dependency>

		<!-- 高亮顯示 -->
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-highlighter</artifactId>
			<version>5.3.1</version>
		</dependency>

步驟三:建一個包名

步驟四:向文件裡寫索引,程式碼如下:

package com.lucene.Demo;

import java.io.File;
import java.io.FileReader;
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;

/**
*   類簡介:
 *           ①簡單的向文件裡寫索引;
 *           ②在根據索引讀取文件;
 *           ③運用路徑來找被索引的文件,找到返回結果
 */
public class Indexer {
	
	//寫索引的例項到指定目錄下
	private IndexWriter writer;
	
	/**
	 * 構造方法:為了例項化IndexWriter
	 */
	public Indexer(String indexDir) throws Exception{
		
		//得到索引所在目錄的路徑
		Directory dir = FSDirectory.open(Paths.get(indexDir));
		
		//例項化分析器
		Analyzer analyzer = new StandardAnalyzer();
		
		//例項化IndexWriterConfig
		IndexWriterConfig con = new IndexWriterConfig(analyzer);
		
		//例項化IndexWriter
		writer = new IndexWriter(dir, con);
	
	}
	
	/**
	 * 關閉寫索引
	 * @throws Exception
	 */
	public void close()throws Exception{
		
		writer.close();
	}
	
	
	/**
	 * 索引指定目錄的所有檔案
	 * @throws Exception 
	 */
	public int index(String dataDir) throws Exception{
		
		//定義檔案陣列,迴圈得出要加索引的檔案
		File[] file = new File(dataDir).listFiles();
		
		for (File files : file) {
			
			//從這開始,對每個檔案加索引
			indexFile(files);
		}
		
		//返回索引了多少個檔案,有幾個檔案返回幾個
		return writer.numDocs();
		
	}

	/**
	 * 索引指定檔案
	 * @throws Exception 
	 */
	private void indexFile(File files) throws Exception {
		
		System.out.println("索引檔案:"+files.getCanonicalPath());
		
		//索引要一行一行的找,,在資料中為文件,所以要得到所有行,即文件
		Document document = getDocument(files);
		
		//開始寫入,就把文件寫進了索引檔案裡去了;
		writer.addDocument(document);
	
	}

	/**
	 * 獲得文件,在文件裡在設定三個欄位
	 * 
	 * 獲得文件,相當於資料庫裡的一行
	 * @throws Exception 
	 * */
	private Document getDocument(File files) throws Exception {
		
		//例項化Document
		Document doc = new Document();
              
                //add():把設定好的索引加到Document裡,以便在確定被索引文件。
		doc.add(new TextField("contents",new FileReader(files)));
		
		//Field.Store.YES:把檔名存索引檔案裡,為NO就說明不需要加到索引檔案裡去
		doc.add(new TextField("FileName", files.getName(), Field.Store.YES));
		
		//把完整路徑存在索引檔案裡
		doc.add(new TextField("fullPath", files.getCanonicalPath(),Field.Store.YES));
	
		//返回document
		return doc;
	}
	
	
	//開始測試寫入索引
	public static void main(String[] args){
		
		//索引指定的文件路徑
		String indexDir = "E:\\luceneDemo";
		
		//被索引資料的路徑
		String dataDir = "E:\\luceneDemo\\data";
		
		//寫索引
		Indexer indexer = null;
		int numIndex = 0;
		
		//索引開始時間
		long start = System.currentTimeMillis();
		
		try {
			//通過索引指定的路徑,得到indexer
			indexer = new  Indexer(indexDir);

			//將要索引的資料路徑(int:因為這是要索引的資料,有多少就返回多少數量的索引檔案)
			numIndex = indexer.index(dataDir);
			
		} catch (Exception e) {
			
			e.printStackTrace();
		}finally{
			try {
				indexer.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		//索引結束時間
		long end = System.currentTimeMillis();
		
		//顯示結果
		System.out.println("索引了  "+numIndex+"  個檔案,花費了  "+(end-start)+"  毫秒");
		
	}

}
寫完索引的顯示效果如下:

步驟五:從文件裡通過索引欄位讀文件,程式碼如下:

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;

/**
 * 
 * 通過索引欄位來讀取文件
 * @author LXY
 *
 */
public class ReaderByIndexerTest {

	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);
		
		//例項化分析器
		Analyzer analyzer=new StandardAnalyzer(); 
		
		//建立查詢解析器
		/**
		 * 第一個引數是要查詢的欄位;
		 * 第二個引數是分析器Analyzer
		 * */
		QueryParser parser=new QueryParser("contents", analyzer);
		
		//根據傳進來的p查詢
		Query query=parser.parse(q);
		
		//計算索引開始時間
		long start=System.currentTimeMillis();
		
		//開始查詢
		/**
		 * 第一個引數是通過傳過來的引數來查詢得到的query;
		 * 第二個引數是要出查詢的行數
		 * */
		TopDocs hits=is.search(query, 10);
		
		//計算索引結束時間
		long end=System.currentTimeMillis();
		
		System.out.println("匹配 "+q+" ,總共花費"+(end-start)+"毫秒"+"查詢到"+hits.totalHits+"個記錄");
		
		//遍歷hits.scoreDocs,得到scoreDoc
		/**
		 * ScoreDoc:得分文件,即得到文件
		 * scoreDocs:代表的是topDocs這個文件陣列
		 * @throws Exception 
		 * */
		for(ScoreDoc scoreDoc:hits.scoreDocs){
			Document doc=is.doc(scoreDoc.doc);
			System.out.println(doc.get("fullPath"));
		}
		
		//關閉reader
		reader.close();
	}
	
	//測試
	public static void main(String[] args) {
		
		String indexDir="E:\\luceneDemo";
		String q="Zygmunt Saloni";
		
		try {
		              search(indexDir,q);
		} catch (Exception e) {
		    // TODO Auto-generated catch block
		     e.printStackTrace();
		}
	}
	
		
}
讀完索引的顯示效果,有幾個檔案裡面有這一句英文。如下:


總結:

              以上就是lucene的簡單的想文件裡寫索引,然後再根據索引來全文搜尋。看到了這,在座的各位同學想必也瞭解了lucene的工作流程,對,就是寫和讀。寫,就是向要檢索的文件寫索引;讀,就是通過索引來搜尋要檢索得到的東西。所以說,當遇到內容非常大的文件,可以使用lucene來檢索,幫助查詢,快速得到資訊。
               
             掌握寫索引的核心程式碼,以及根據索引讀取文件。
注意:

              1、索引指定的文件路徑的時候,在程式碼中為E:\\luceneDemo,必須為被索引檔案的正確路徑,否則會出現以下異常:
    org.apache.lucene.index.IndexNotFoundException: no segments* file found in [email protected]:\luceneDemo     [email protected]: files: []
    at org.apache.lucene.index.SegmentInfos$FindSegmentsFile.run(SegmentInfos.java:726)
    at org.apache.lucene.index.StandardDirectoryReader.open(StandardDirectoryReader.java:50)
    at org.apache.lucene.index.DirectoryReader.open(DirectoryReader.java:63)
    at readerByIndexer.ReaderByIndexerTest.search(ReaderByIndexerTest.java:32)
    at readerByIndexer.ReaderByIndexerTest.main(ReaderByIndexerTest.java:87)
                   出現上述的問題有兩個:第一是沒有找到D:\\luceneDemo資料夾下的檔案。有時還會出現空指標的異常。第二是沒有關閉indexer

              2、當寫完索引後,想在測試一遍,先把被索引檔案的資料夾下所產生的檔案先刪除,如若不刪除,就是檢索到重複的文件。    
              3、測試的引數和路徑必須確定是完全正確的,有其是要查詢的引數,否則會查到0個文件。

              4、這會需要檢索的文件必須為全英文。

              5、注意導包是否正確。


溫馨提示:

            簡單向指定文件寫索引,需要大家熟練掌握,懂得每個核心詞的用法。那麼lucene入門學習就到這裡,接下來就是對 被索引文件的一個CRUD。


相關推薦

Lucene學習筆記簡介索引讀取

什麼是lucene? lucene就是一個全文檢索的工具包。 Lucene的能幹什麼? 1.      獲取內容(Acquire Content) Lucene不提供爬蟲功能,如果需要獲取內容需要自己建立爬蟲應用。 Lucene只做索引和搜尋工作。 2.建立文件(Buil

DSP——DSP/BIOS學習筆記——TSKMBX

1、它們都是任務間通訊的手段,但是應用場合不同  訊號量用作任務同步或者資源的互斥訪問 至於郵箱,名副其實的,可以“郵寄”一些東東給別的任務 舉個例子的話,我覺得可以說訊號量就像別人打你電話只響一下(具體代表什麼含義在於你們之間的約定),而郵箱就像簡訊哇,寫啥都行。當然,二進位制訊號量也可以用郵箱實現。 2、

流媒體技術學習筆記Nginx-Rtmp-Module統計某頻道在線觀看流的客戶數

sele lec rest uri class origin 客戶 擴展 raw 獲得訂閱者人數,可以方便地顯示觀看流的客戶數。 查看已經安裝好的模塊 /usr/local/nginx/sbin/nginx -V 安裝從源編譯Nginx和Nginx-RTMP所

從Paxos到Zookeeper分散式一致性原理與實踐 讀書筆記 分散式架構

1.1 從集中式到分散式  1 集中式特點  結構簡單,無需考慮對多個節點的部署和節點之間的協作。  2  分散式特點 分不性:在時間可空間上隨意分佈,機器的分佈情況隨時變動 對等性:計算機之間沒有主從之分,所有計算機之間是對等的。副本是分散式系統對資料

機器學習筆記7——聚類演算法

對於監督學習,訓練資料都是事先已知預測結果的,即訓練資料中已提供了資料的類標。無監督學習則是在事先不知道正確結果(即無類標資訊或預期輸出值)的情況下,發現數據本身所蘊含的結構等資訊。 無監督學習通過對無標記訓練樣本的學習來尋找這些資料的內在性質。 聚類的目標是發現數據中自然形成的分組,使得每

吳恩達老師機器學習筆記SVM

時隔好久沒有再拾起機器學習了,今日抽空接著學 今天是從最簡單的二維資料分類開始學習SVM~ (上圖為原始資料) SVM的代價函式 這裡套用以前logistic迴歸的模板改一下下。。 load('ex6data1.mat'); theta=rand(3,1); [

Stereo Matching文獻筆記:《On Building an Accurate Stereo Matching System on Graphics Hardware》讀後感

(轉載:http://blog.csdn.net/wsj998689aa/article/details/49403353, 作者:迷霧forest) 目錄(?)[-] 演算法詳解 適合並行 特徵融合 自適應區域  

Android學習筆記——Activity

1.什麼是Activity       (1)Activity是一個應用程式元件       (2)為應用程式提供一個視覺化頁面       (3)使用者通過此頁面與應用程式互動 2.啟動Act

深度學習筆記VGG + 動量法

新開個坑,作為最近一直忙不寫部落格的一個補償。 在筆記篇中,主要會以流水賬(日記)的形式,覺得囉嗦的朋友可以關注我的後續篇節,有一些Project會單獨拿出來說。 先講個題外話。 因為經常需要更新github上老師的程式碼,於是很多人想要在本地與專案保持更新 通過 g

【GANs學習筆記初步瞭解GANs

** 第一章 初步瞭解GANs ** ** 1. 生成模型與判別模型 ** 理解對抗網路,首先要了解生成模型和判別模型。判別模型比較好理解,就像分類一樣,有一個判別界限,通過這個判別界限去區分樣本。從概率角度分析就是獲得樣本x屬於類別y的概率,是一個條件概率P(

【PhotonEngine 學習筆記簡單使用

【PhotonEngine 學習筆記】(一)簡單使用 前言 PhotonEngine簡介 Photon SDKs SDK:SELF-HOSTED 下載安裝 伺服器端邏輯 建立自己的伺服器專案(類庫)

Libcap庫學習::簡介

Libpcap是Packet Capture library的英文縮寫,即資料包捕獲函式庫,該庫提供的C函式介面用於捕獲經過指定網路介面(通過將網絡卡設定為混雜模式,可以捕獲所有經過該網路介面的資料包)的資料包。 Libpcap面向上層應用,提供了使用者級別的網路資料包捕獲介面,在系統部署時

node.js學習筆記整理

(1)node Node.js 是一個基於 Chrome V8 引擎的 JavaScript 執行環境。 Node與javaScript的區別在於,javaScript的頂層物件是window,而node是global //這裡使用的var宣告的變數不是全域性的,是當前模組下的,用global宣告的表示是

【Java】Java學習筆記總結

2013-07-15 1. JDK、JRE和JVM分別是什麼,區別是什麼? 答: ①、JDK 是整個Java的核心,包括了Java執行環境、Java工具和Java基礎類庫。 ②、JRE(Java Runtime Environment,Java執行環境),執行JAVA程式所

【JVM學習筆記jvm初體驗-記憶體溢位問題分析及解決方案

####1、開始 建立Main類和Demo類,在Main類的main方法中建立List,並向List中無限建立Demo物件,造成記憶體溢位, 並輸出記憶體溢位錯誤檔案在專案目錄下,為了使等待時間減小,設定執行堆記憶體大小。 ####2、建立Demo類 package com.ch

機器學習筆記4——Fisher分類器線性判別分析,LDA

本博文為Fisher分類器的學習筆記~本博文主要參考書籍為:《Python大戰機器學習》Fisher分類器也叫Fisher線性判別(Fisher Linear Discriminant),或稱為線性判別分析(Linear Discriminant Analysis,LDA)。

js學習記錄require 與module.exports

1. js 裡面的程式碼可以放在不同的檔案裡,稱為程式碼模組2.當一個模組需要引用其他模組中程式碼的時候,就用require匯入相應的模組(使用程式碼塊),用module.exports指向一個程式碼塊(製作程式碼塊)3.  檔案1.js var codeUtils =

QT5.11.1結合VS2017學習筆記環境的配置及HelloWorld的實現

前言:       最近開始學習QT,由於習慣了使用VS而網上的教程大多都是基於QTCreator的,很少有基於VS的。為此,本人決定將自己學習的過程記錄下來。水平有限,有不對的地方,歡迎大家批評指正! 工具及系統:VS2017,Qt5.11.1 一、環境配置 1、安

Hadoop學習筆記WordCount執行

前言:本文是在hadoop已經配置好的情況下 WordCount是hadoop下的HelloWorld程式,是初學者必須要會的。下面是用eclipse進行開發 一、工程與MapReduce程式碼 新建工程,建立WordCount class

3.Zedboard學習筆記安裝vivado獲取license

按部就班安裝vivado,需要時間比較長,最後會彈出如下視窗,要求提供license。 1.註冊xilinx賬號 2.填寫相關資訊,是xilinx強制要求填寫的 3.進入網頁: http://www.xilinx.com/getlicense