1. 程式人生 > >Lucene介紹及入門程式

Lucene介紹及入門程式

1.資料分類
結構化資料:指具有固定格式或有限長度的資料,如資料庫,元資料等。
非結構化資料:指不定長或無固定格式的資料,如郵件,word文件等磁碟上的檔案
2.非結構化資料查詢方法
(1)順序掃描法:
所謂順序掃描,比如要找內容包含某一個字串的檔案,就是一個文件一個文件的看,對於每一個文件,從頭看到尾,如果此文件包含此字串,則此文件為我們要找的檔案,接著看下一個檔案,直到掃描完所有的檔案。如利用windows的搜尋也可以搜尋檔案內容,只是相當的慢
(2)全文檢索
將非結構化資料中的一部分資訊提取出來,重新組織,使其變得有一定結構,然後對此有一定結構的資料進行搜尋,從而達到搜尋相對較快的目的。這部分從非結構化資料中提取出的然後重新組織的資訊,我們稱之索引。
這種先建立索引,在對索引進行搜尋的過程就叫全文檢索。
3.如何實現全文檢索
可以使用Lucene實現全文檢索。Lucene是apache下的一個開放原始碼的全文檢索引擎工具包。提供了完整的查詢引擎和索引引擎,部分文字分析引擎。Lucene的目的是為軟體開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能。
4.索引和搜尋流程圖
(1)索引過程,對要搜尋的原始內容進行索引構建一個索引庫,索引過程包括:
確定原始內容即要搜尋的內容採集文件建立文件分析文件索引文件
(2)搜尋過程,從索引庫中搜索內容,搜尋過程包括:使用者通過搜尋介面建立查詢執行搜尋,從索引庫搜尋渲染搜尋結果
5.建立文件物件
在索引前需要將原始內容建立成文件,文件中包括一個一個的域(field),域中儲存內容。
這裡我們可以將磁碟上的一個檔案當成一個document,Document中包括一些Field(file_name檔名稱、file_path檔案路徑、file_size檔案大小、file_content檔案內容)

注意:每個Document可以有多個Field,不同的Document可以有不同的Field,同一個Document可以有相同的Field(域名和域值都相同)

每個文件都有一個唯一的編號,就是文件id.

6.分析文件
將原始內容建立為包含域(Field)的文件(document),需要再對域中的內容進行分析,分析的過程是經過對原始文件提取單詞、將字母轉為小寫、去除標點符號、去除停用詞等過程生成最終的語彙單元,可以將語彙單元理解為一個一個的單詞。
每個單詞叫做一個Term,不同的域中拆分出來的相同的單詞是不同的term。term中包含兩部分一部分是文件的域名,另一部分是單詞的內容
7.建立索引的步驟
第一步:建立一個java工程,並匯入jar包。
第二步:建立一個indexwriter物件。
1)指定索引庫的存放位置Directory物件
2)指定一個分析器,對文件內容進行分析。
第二步:建立document物件。
第三步:建立field物件,將field新增到document物件中。
第四步:使用indexwriter物件將document物件寫入索引庫,此過程進行索引建立。並將索引和document物件寫入索引庫。
第五步:關閉IndexWriter物件。
8.Field域的屬性
是否分析:是否對域的內容進行分詞處理,前提是我們要對域的 內容進行查詢
是否索引:將Field分析後的詞進行索引,只有索引方可所搜到
是否儲存:將Field值存在文件中,儲存在文件中的Field才可以從Document中獲取

9.建立索引的程式碼(需要導包)

public class FirstLucene {
@Test
	public void testIndex() throws Exception{
	Directory directory=FSDirectory.open(new File("D:\\資料\\index"));
	Analyzer analyzer=new StandardAnalyzer();//官方推薦分析器
	IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_4_10_3,analyzer);
	IndexWriter indexWriter=new IndexWriter(directory,config);
	//建立四個域物件(檔名,檔案大小,檔案內容,檔案路徑)
	//先把檔案讀到記憶體中使用IO流
	File f=new File("D:\\資料\\searchsource");
	File[] listFiles=f.listFiles();
	for(File file:listFiles){
		//建立文件物件
		Document document=new Document();
		//檔名字
		String file_name=file.getName();
		Field fileNameField=new TextField("fileName",file_name,Store.YES);
		
		//檔案大小
		long file_size=FileUtils.sizeOf(file);
		Field fileSizeField=new LongField("fileSize",file_size,Store.YES);
		//檔案路徑
		String file_path=file.getPath();
		Field filePathField=new StoredField("filePath",file_path);
		//檔案內容
		String file_content=FileUtils.readFileToString(file);
		Field fileContentField=new TextField("fileContent",file_content,Store.NO);
		//將域物件放到文件物件
		document.add(fileNameField);
		document.add(fileSizeField);
		document.add(filePathField);
		document.add(fileContentField);
		//使用indexwriter物件將document物件寫入索引庫,此過程進行索引建立,並將索引和document物件放入索引庫
		indexWriter.addDocument(document);
	}
	//關閉IndexWriter物件
	indexWriter.close();
}
10.查詢索引步驟
第一步:建立一個Directory物件,也就是索引庫存放的位置。
第二步:建立一個indexReader物件,需要指定Directory物件。
第三步:建立一個indexsearcher物件,需要指定IndexReader物件
第四步:建立一個TermQuery物件,指定查詢的域和查詢的關鍵詞。
第五步:執行查詢。
第六步:返回查詢結果。遍歷查詢結果並輸出。
第七步:關閉IndexReader物件

11.查詢索引程式碼實現

@Test
	public void testSearch()throws Exception{
		//建立一個Directory物件,也就是索引庫位置
	Directory directory=FSDirectory.open(new File("D:\\資料\\index"));
	//建立一個IndexReader物件,需要指定directory物件
	IndexReader indexReader=DirectoryReader.open(directory);
	//建立一個IndexSearch物件,需要指定indexReader物件
	IndexSearcher indexSearch=new IndexSearcher(indexReader);
	//建立一個TermQuery物件,指定查詢的域和查詢的關鍵詞
	Query query=new TermQuery(new Term("fileName","apache"));
	//執行查詢
	TopDocs topDocs=indexSearch.search(query, 2);
	//返回查詢結果,遍歷查詢結果並返回
	ScoreDoc[] scoreDocs=topDocs.scoreDocs;
	for(ScoreDoc scoreDoc:scoreDocs){
		int doc=scoreDoc.doc;
		Document document=indexSearch.doc(doc);
		//檔名稱
		String fileName=document.get("fileName");
		System.out.println(fileName);
		//檔案內容
		String fileContent=document.get("fileContent");
		System.out.println(fileContent);
		//檔案大小
		String fileSize=document.get("fileSize");
		System.out.println(fileSize);
		//檔案路徑
		String filePath=document.get("filePath");
		System.out.println(filePath);

	}
	//關閉流
	indexReader.close();
}
13.分析器
從一個Reader字元流開始,建立一個基於Reader的Tokenizer分詞器,經過三個TokenFilter生成語彙單元Tokens。
要看分析器的分析效果,只需要看Tokenstream中的內容就可以了。每個分析器都有一個方法tokenStream,返回一個tokenStream物件。

14.分析器的分詞效果

@Test
public void testTokenStream() throws Exception {
	//建立一個標準分析器物件
	//Analyzer analyzer = new StandardAnalyzer();
	//Analyzer analyzer = new SmartChineseAnalyzer();
	Analyzer analyzer = new IKAnalyzer();
	//獲得tokenStream物件
	//第一個引數:域名,可以隨便給一個
	//第二個引數:要分析的文字內容
	TokenStream tokenStream = analyzer.tokenStream("test", "The Spring Framework provides a comprehensive programming 

and configuration model.");
	//新增一個引用,可以獲得每個關鍵詞
	CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
	//新增一個偏移量的引用,記錄了關鍵詞的開始位置以及結束位置
	OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
	//將指標調整到列表的頭部
	tokenStream.reset();
	//遍歷關鍵詞列表,通過incrementToken方法判斷列表是否結束
	while(tokenStream.incrementToken()) {
		//關鍵詞的起始位置
		System.out.println("start->" + offsetAttribute.startOffset());
		//取關鍵詞
		System.out.println(charTermAttribute);
		//結束位置
		System.out.println("end->" + offsetAttribute.endOffset());
	}
	tokenStream.close();
}