1. 程式人生 > >[Java Web]Java的全文搜尋類庫 Lucene

[Java Web]Java的全文搜尋類庫 Lucene

Lucene是apache軟體基金會4 jakarta專案組的一個子專案,是一個開放原始碼的全文檢索引擎工具包,即它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文字分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟體開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎。

Lucene的實現機制是倒排表。例如現在有2個文件需要建立索引,內容分別為"Lucene Learning"和"Lucene Hadoop",建立後的索引實際是這樣的:

索引的優勢在於:雖然建立索引會比較耗時,但是在一次建立後便可以永遠支援高效的查詢。

Lucene的核心類有:

Directory:索引物件,常用有RAMDirectory和FSDirectory兩種,前者代表一個記憶體中的索引檔案,後者代表一個本地的索引檔案。

Filed:欄位,由name和value組成,常用的欄位分為三種:

  1. StoredFiled:僅用來儲存資料的欄位,該欄位的資料不會建立索引。
  2. StringFiled、LongFiled等:將資料整體建立為索引的欄位。
  3. TextFiled:將資料分詞並建立索引的欄位。

Document:索引中儲存的文件結構,一個文件由多個欄位組成。

Term:詞元,相當於索引中的鍵,每個Term都指向一個由文件組成的連結串列。

IndexReader:索引的讀取流,可以從索引中讀取出需要的文件。

IndexWriter:索引的輸出流,將文件寫入索引。

IndexSearcher:索引的搜尋功能。

Query:搜尋條件。

Analyzer:分詞器,可以將欄位中的資料分解成多個詞元。

Lucene的流程:


寫入:將資料來源轉換為文件,然後使用IndexWriter的addDocument方法將文件新增到索引。

查詢:使用IndexReader獲取一個IndexSearcher物件,並建立一個Query物件指定查詢型別,然後使用IndexSearcher的search方法得到文件。

程式碼例項:

新增索引:

public static void init() throws IOException {
	//索引檔案
	Directory dir = FSDirectory.open(new File("E:/index"));
	//索引配置(指定Lucene版本和分詞器)
	IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_0, new StandardAnalyzer());
	//得到輸出流
	IndexWriter writer = new IndexWriter(dir, config);
	//建立文件
	Document doc = new Document();
	//id會以一個整體被作為詞元被索引 並且會被儲存在文件中
	doc.add(new StringField("id", "123", Field.Store.YES));
	//content會被分詞器分割成數個詞元被索引 但不會儲存在文件中
	doc.add(new TextField("content", "Lucene是apache軟體基金會4 jakarta" +
			"專案組的一個子專案,是一個開放原始碼的全文檢索引擎工具包,即它不是一個完整的全文檢索引擎," +
			"而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎," +
			"部分文字分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟體" +
			"開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的" +
			"功能,或者是以此為基礎建立起完整的全文檢索引擎。", Field.Store.NO));
	//address會被分詞器分割成數個詞元被索引 並且會儲存在文件中
	doc.add(new TextField("address", "北京市海淀區翠微路凱德大廈", Field.Store.YES));
	//將文件新增到索引
	writer.addDocument(doc);
	//列印當前已經被索引的文件個數
	System.out.println("被索引的文件個數:" + writer.numDocs());
	writer.close();
}

遍歷索引中所有的文件:

public static void ergodic() throws IOException {
	//索引檔案
	Directory dir = FSDirectory.open(new File("E:/index"));
	//得到輸入流
	IndexReader reader = DirectoryReader.open(dir);
	IndexSearcher searcher = new IndexSearcher(reader);
	Document doc = null;
	for (int i = 0; i < reader.maxDoc(); i++) {
		doc = searcher.doc(i);
		System.out.println("Doc [" + i + "] : id: "
				+ doc.get("id") + ", desc: " + doc.get("content"));
	}

}
搜尋文件:
public static void search() throws IOException, ParseException {
	//索引檔案
	Directory dir = FSDirectory.open(new File("E:/index.txt"));
	//輸入流
	IndexReader reader = DirectoryReader.open(dir);
	IndexSearcher searcher = new IndexSearcher(reader);
	// 搜尋條件
	QueryParser parser = new QueryParser("desc",
			new StandardAnalyzer());
	Query query = parser.parse("索引檔案");
	// 搜尋結果
	TopDocs hits = searcher.search(query, 2);
	System.out.println("查詢出來的總數是:" + hits.totalHits);
	// 獲取搜尋結果
	Document doc = null;
	for (ScoreDoc scoreDoc : hits.scoreDocs) {
		doc = searcher.doc(scoreDoc.doc);
		System.out.println("Doc [" + scoreDoc.doc + "] : id: "
				+ doc.get("id") + ", desc: " + doc.get("content"));
	}
}

一些細節:
  1. 對於一個索引檔案,同時只能有一個輸出流對它進行操作.
  2. 為了避免頻繁的I/O操作,可以先將索引建立在RAMDirectory中,然後一次性寫入本地檔案。
  3. 中文分詞庫比較好用的有Ansj和IK,可以自行百度瞭解。
  4. Lucene不支援去重,DuplicateFilter會先將索引進行去重後在進行條件查詢,這樣會造成資料缺失。
  5. 索引的更新可以先根據詞元刪除原本的文件後再新增新的文件,在批量操作時效率很高。

相關推薦

[Java Web]Java全文搜尋 Lucene

Lucene是apache軟體基金會4 jakarta專案組的一個子專案,是一個開放原始碼的全文檢索引擎工具包,即它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文字分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟體

當一個被載入後,它的靜態變數生命週期是什麼,是整個應用程式執行結束(比如java web程式,從載入到伺服器關閉還是該執行緒執行完畢)還是別的什麼?

靜態變數在記憶體中只有一個,JAVA虛擬機器載入類的時候為其分配記憶體,位於方法區,被類的所有例項共享,其生命週期取決於類的生命週期。。。當類被解除安裝。。。靜態變數也被銷燬 取決於類載入器。如果換了一個類載入器,這個

深入理解Java 8 Lambda 語言篇

http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features/ http://zh.lucida.me/blog/java-8-lambdas-inside-out-library-features/

Java的4種Json介紹

JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。 易於人閱讀和編寫。同時也易於機器解析和生成。 它基於JavaScript Programming Language, Standard ECMA-262 3rd Edition

小型Java Web專案之使用者JavaBean

這兩個月複習了一下去年所學的Java Web開發,因此也寫了一個小型的Java Web專案,這個專案雖然比較小,但是還是用了DAO+MVC模式,目的在於好好熟悉一下這兩個模式。 登陸使用者類的JavaBean如下: package vo; public

Java核心技術梳理-基礎

運行環境 http 定量 pattern 範圍 pareto datetime abcde 大小 一、引言 Oracle為Java提供了豐富的基礎類庫,Java 8 提供了4000多個基礎類庫,熟練掌握這些基礎類庫可以提高我們的開發效率,當然,記住所有的API是不可

Java Web----Java Web的資料庫操作(一)

Java Web的資料庫操作 一、JDBC技術 1、JDBC簡介        JDBC是Java程式與資料庫系統通訊的標準API,它定義在JDK的API中,通過JDBC技術,Java程式可以非常方便

Java核心-IO-文件過濾器(FilenameFilter)

return 文件過濾 system sof boolean style 接口 strong family 文件操作過濾器(FilenameFilter): listFiles(FilenameFilter filter )方法 : 實際就相當於: //文件過濾器(Fil

Java核心-IO-字符解碼和編碼操作

編碼 亂碼 .cn 字符 字符串 tro com str 數組 編碼:把字符串轉換為byte數組。 解碼:把byte數組轉換為字符串。 一定要保證編碼和解碼的字符集相同,否則亂碼。 Java核心類庫-IO-字符解碼和編碼操作

Java核心-IO-字節數組流/內存流

sta throws demo print char 字符數 lang java 字節數組 內存流(數組流):   把數據先臨時存在數組中,待會再從數組中獲取出來。   1. 字節內存流:ByteArrayInputStream/ByteArrayOutputStream

Java核心-IO-對象流(實現序列化與反序列化)

.get throws 反序 code row cts new java cep 使用對象流來完成序列化和反序列化操作:   ObjectOutputStream:通過writeObject()方法做序列化操作的   ObjectInputStream:通過readObje

Java核心-IO-打印流(PrintStream/PrintWriter)

int div leo obj clas 打印流 println 不換行 pan 打印流,打印數據的,打印流只能是輸出流: PrintStream:字節打印流。 PrintWriter:字符打印流。 對於PrintWriter來說,當啟用字段刷新之後 PrintWrite

Java核心-IO-NIO概述

字符 java 傳統 ont syn 概述 pan spa 數據 NIO:New IO 從JDK1.4開始提出的,新的IO,可以把一塊磁盤文件映射到內存中,我們再去讀取內存中的數據。 存放在java.nio包中 Java NIO(New IO)是Java1.4版本開始引入的

JAVALinkList的基本實現

ble set tof nts rem marker ext err bounds 寫完調試了好久,邊界不優點理,具體的請看JDK類庫,下面僅僅是基本實現:import java.util.Iterator; /** * 類名:MyLinkedList 說明:Lin

Java異步執行多個HTTP請求的例子(需要apache http

ride 同步 conn done 例子 latch block org ftw 直接上代碼 package org.jivesoftware.spark.util; import java.io.IOException; import java.uti

java web 工程找不到tomcat java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

ood cep 找不到 otf 技術分享 .get http except 分享 ava.lang.ClassNotFoundException: com.mysql.jdbc.Driverat org.apache.catalina.loader.WebappClassL

java-web——第十一課 時間

osc 題目 其中 ima cal pid end 不能 sch 前言: 在我們學習java web之中,實體類的屬性經常會遇到時間類 時間類也是一個很重要的類, 首先我們先了解一下經常使用的時間類 經常使用的時間類也就是這三個類 具體的可以查閱api http://to

Java之基本學習

decimal ren 常量池 blog 新建 random類 使用 ring org  JAVA基本類庫:   (一),輸入相關     main(String[] args):設置輸入參數     輸入類;Scanner:Scanner sc=new Scanner(S

java 基礎之 SQLFun

cnblogs import bsp 轉換 span pre param ack urn package com.exjor.webdemo; import java.sql.Timestamp; import java.util.Date; public

java 基礎之 FormatFun

final mat web port efault div break orm log package com.exjor.webdemo; import java.text.SimpleDateFormat; import java.util.Date;