Lucene 6.2.1入門教程(一) 建立索引和基本搜尋索引
簡單說兩句,Lucene現在高版本的教程很少,網上基本是4.0以下的,目前最新版是6.2.1,所以我試著來寫寫這個版本的教程。
至於那些概念什麼的,我就不多說了,大家可以參考以前的舊教程來了解Lucene的體系結構和基本原理。大致說一下Lucene就是通過建立索引這個類似書目錄那樣的東西來提升查詢效率的一個框架,所謂索引我理解就是將文件等資料來源的不同組成部分的指示標誌,索引會指引使用者快速找到這些資料來源不同組成部分。
多了不說了,先看程式碼吧,首先是Indexer類,用來建立索引:
public class Indexer {
private IndexWriter writer;//這個類用來寫入索引
//下面這個類是FileFilter的實現類,用來過濾符合條件的文件。
private static class TextFilesFilter implements FileFilter{
@Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
return pathname.getName().toLowerCase().endsWith(".txt");
}
}
//構造方法,用來傳入索引存放路徑
public Indexer(String indexDir) throws IOException{
Directory dir=FSDirectory.open(Paths.get(indexDir));
IndexWriterConfig config=new IndexWriterConfig(new StandardAnalyzer());
config.setOpenMode(OpenMode.CREATE_OR_APPEND);
writer=new IndexWriter(dir,config);
}
//關閉indexWriter
public void close() throws IOException{
writer.close();
}
//這個方法是遍歷資料夾下所有檔案並選擇符合條件檔案寫入索引的方法,返回寫入的文件總數
public int index(String dataDir,FileFilter filter) throws IOException{
File[] files=new File(dataDir).listFiles();
for(File file:files){
if(!file.isDirectory() && !file.isHidden()
&& file.exists()
&& file.canRead()
&& (filter==null) || filter.accept(file)){
indexFile(file);
}
}
return writer.numDocs();
}
//這個方法是寫入索引的方法,將生成的document物件寫入到索引中
private void indexFile(File file) throws IOException{
System.out.println("indexing..."+file.getCanonicalPath());
Document doc=getDocument(file);
writer.addDocument(doc);
}
//這個方法是生成Document物件的方法,Document物件就是對文件各個屬性的封裝
protected Document getDocument(File file) throws IOException{
Document doc=new Document();
doc.add(new Field("contents",new FileReader(file),TextField.TYPE_NOT_STORED));
doc.add(new Field("filename",file.getName(),TextField.TYPE_STORED));
doc.add(new Field("fullpath",file.getCanonicalPath(),TextField.TYPE_STORED));
return doc;
}
public static void main(String[] args) throws IOException {
String indexDir="C:/lucene_index";
String dataDir="C:/lucene_data";
long start=System.currentTimeMillis();
Indexer indexer=new Indexer(indexDir);
int numberIndexed=indexer.index(dataDir, new TextFilesFilter());
indexer.close();
long end=System.currentTimeMillis();
System.out.println(numberIndexed);
System.out.println(end-start);
}
}
我說一下幾個需要注意的地方。
Directory dir=FSDirectory.open(Paths.get(indexDir));這個方法是獲取索引存放路徑的方法,早期版本的Lucene在open方法中用new File或new一個輸入流的方式獲取路徑,目前這裡採用的是nio的方式獲取資料夾路徑,效率較高。
IndexWriterConfig config=new IndexWriterConfig(new StandardAnalyzer());
config.setOpenMode(OpenMode.CREATE_OR_APPEND);
writer=new IndexWriter(dir,config);
這裡IndexWriterConfig物件是IndexWriter的配置物件,有很多配置。第二行的openMode是索引路徑開啟的方式,這裡選擇的是建立或追加內容。
然後就是初始化一個IndexWriter,這裡與早期版本也有所不同,將配置物件傳入構造方法。
doc.add(new Field("contents",new FileReader(file),TextField.TYPE_NOT_STORED));
doc.add(new Field("filename",file.getName(),TextField.TYPE_STORED));
這是為Document物件新增屬性的方法,與早期版本的也有所不同,第一個是將檔案內容用輸入流的方式寫入,其中Field物件第三個引數是TextField.TYPE_NOT_STORED,我的理解就是索引中不儲存這個流以及流讀取的內容本身
然後看一下IndexSearcher就是搜尋索引的類:
public class Searcher {
//這個方法是搜尋索引的方法,傳入索引路徑和查詢表示式
public static void search(String indexDir,String query) throws IOException, ParseException{
Directory dir=FSDirectory.open(Paths.get(indexDir));
IndexSearcher searcher=new IndexSearcher(DirectoryReader.open(dir));
QueryParser parser=new QueryParser("contents",new StandardAnalyzer());
Query q=parser.parse(query);
long start=System.currentTimeMillis();
TopDocs hits=searcher.search(q, 10);
long end=System.currentTimeMillis();
System.out.println(hits.totalHits);
System.out.println(end-start);
for(ScoreDoc scoreDoc:hits.scoreDocs){
Document doc=searcher.doc(scoreDoc.doc);
System.out.println(doc.get("fullpath"));
}
}
public static void main(String[] args) throws IOException, ParseException {
String indexDir="C:/lucene_index";
String query="netty";
search(indexDir, query);
}
}
這裡需要注意的是這些:
IndexSearcher searcher=new IndexSearcher(DirectoryReader.open(dir));這個IndexSearcher初始化的過程也和早期版本有所不同,看原始碼構造方法引數是IndexReader這個抽象類的子類,我根據原始碼找到了DirectoryReader這個子類比較合適,用open方法獲得了索引路徑,然後IndexSearcher的構造方法傳入這個IndexReader子類。
QueryParser parser=new QueryParser("contents",new StandardAnalyzer());
Query q=parser.parse(query);
這裡就是解析查詢語句以及要查詢的Document屬性,換句話說就是在哪兒查?查什麼?怎麼查?
TopDocs hits=searcher.search(q, 10);
這個方法查詢出前10個符合要求的文件。
for(ScoreDoc scoreDoc:hits.scoreDocs){
Document doc=searcher.doc(scoreDoc.doc);
System.out.println(doc.get("fullpath"));
}
這裡就是遍歷每個查詢到的文件,以及打印出每個查詢到的文件的fullpath屬性。
基本寫入讀取索引程式就這些。
歡迎加入qq群204058911,群主是Lucene和Solr方面的大牛,著有Solr實戰這一本經典教科書。
相關推薦
Lucene 6.2.1入門教程(一) 建立索引和基本搜尋索引
簡單說兩句,Lucene現在高版本的教程很少,網上基本是4.0以下的,目前最新版是6.2.1,所以我試著來寫寫這個版本的教程。 至於那些概念什麼的,我就不多說了,大家可以參考以前的舊教程來了解Lucene的體系結構和基本原理。大致說一下Lucene就是通過建立索引這
Django 2.1入門教程(一)
開發環境 pip install Django==2.1 簡介 本文通過建立一個簡單的投票網站來演示Django的基本用法。 首先檢視已安裝的Django的版本: py -m django --version Django 2.1支援Python 3.5及以後版本
ECMAScript 6.0基礎入門教程(一)-ES6基礎入門教程
ECMAScript 6.0基礎入門教程(一) 1、ES6簡介 1.1 ES6的歷史 ECMAScript簡稱ECMA或ES ECMAScript與JavaScript的關係 ECMA是European Computer Manu
Django 2.1入門教程(四)
本文將集中講解處理表單和精簡我們的程式碼。 寫一個簡單的表單 編輯polls/detail.html檔案如下: <h1>{{ question.question_text }}</h1> {% if error_message %}<p&
Vue.js 2.0 入門教程(一) 搭建開發環境
最近,前段開發框架層出不窮,響應式和模組化開發框架一下變得炙手可熱起來。在這樣的大浪潮下,我也開始進入vue的學習行列中。 這裡有觀眾會問,為什麼選擇vue呢? 小編作為一個剛入門前端的小白,vue 相比於angular2 ,react,入門簡單容易上手,簡單也是效
寫給前端同學的C++入門教程(一):概述和環境搭建
說明:本人是前端er,因為最近對 UE4(一個遊戲開發引擎)產生了興趣,而這個引擎源開發遊戲時需要用到 C++ ,所以就開始入坑 C++ 了。現將自己學習 C++ 的筆記整理並分享出來,以便一些想入門 C++ 的朋友一起學習,將會以系列教程的的形式來編寫,這是第一篇。 ## C++ 是什麼? 我們都知道,目
大資料學習初級入門教程(一) —— Hadoop 2.x 的安裝、啟動和測試
大資料最基礎的就是資料的儲存和計算,而 Hadoop 就是為儲存和計算而生,是最基礎的大資料處理工具。這篇簡單寫寫 Hadoop 2.x 的安裝,啟動和測試。 一、準備環境 大資料環境的部署,一般都是叢集,機器數量為奇數,這裡以 5 臺機器為例,作業系統為 CentOS 6.9_x64;
JavaScript基礎入門教程(一)
構造 圖片 def type 屬於 string 意思 原則 原始類型 js的數據類型 雖然js屬於弱類型語言,但其總共有6種數據類型。弱類型的意思是定義的變量沒有類型的區分,比如先執行 var num=123; 定義了一變量num存儲整數,可接下來執行 num="he
Docker入門教程(一)介紹
操作 AC font start 一個 namespace com 下載地址 div 1.1docker是什麽: Docker是通過內核虛擬化技術(namespaces及cgroups cpu、內存、磁盤io等)來提供容器的資源隔離與安全保障等。由於Docker通過操作系統
Asp.net Core IdentityServer4 入門教程(一):概念解析
什麽 ica 統一 理解 給他 分享 目錄 .net 系統 目錄 1、IdentityServer4 是什麽 2、什麽是OpenID和OAuth 2.0協議 3、IdentityServer4 可以用來做什麽 其他 1、IdentityServer4 是什麽 Ident
CMake入門教程(一)
之前的一篇部落格介紹了CMake一些簡單的基礎情況:CMake的簡介、安裝以及基本的使用 現在一起來學習一下CMakeLists的基礎命令。 ※※※※※※※※※※※※※※※※※※※※※※CMake的基本使用語法※※※※※※※※※※※※※※※※※※※※※※※※※※※ ①CMake使用$
Koa快速入門教程(一)
Koa 是由 Express 原班人馬打造的,致力於成為一個更小、更富有表現力、更健壯的 Web 框架,採用了async和await的方式執行非同步操作。 Koa有v1.0與v2.0兩個版本,隨著node對async和await的支援,Koa2的正式釋出,本文Koa均
React入門教程(一)
一、HTML 模板 使用 React 的網頁原始碼,結構大致如下。 <!DOCTYPE html> <html> <head> <script src="../build/react.js"></script>
Scrapy入門教程(一)
既然你點進來看了,我就預設你知道什麼是爬蟲了。不知道也沒有關係,來看一下爬蟲的定義:網路爬蟲,是一種按照一定的規則,自動地抓取全球資訊網資訊的程式或者指令碼。可以寫爬蟲的語言、框架有很多,這裡記錄一下Scrapy的入門教程。 一、為什麼要選擇Scrapy? Scrapy有名氣,只要你做過爬蟲就基本上
Spring框架入門教程(一)——框架簡介
介紹 Spring是一個分層的(一站式) 輕量級開源框架 Spring的核心是控制反轉(IoC)和麵向切面(AOP) 為什麼說分層一站式呢? javaEE分三層開發 WEB層,業務層,持久層。在ssh整合框架中s == Struts2, s == spring,h
scrapy入門教程(一)虛擬環境的搭建
1、安裝virtualenvwrapper-win 包。使用命令pip install virtualenvwrapper-win 2、輸入workon命令檢視是否可用。此時找不到檔案是正常的,因為我們還沒有開始建立虛擬環境。 3、開始建立虛擬環境。使用命令
OpenMP入門教程(一)
什麼是OpenMP Open Multi-Processing的縮寫,是一個應用程式介面(API),可用於顯式指導多執行緒、共享記憶體的並行性。 在專案程式已經完成好的情況下不需要大幅度的修改原始碼,只需要加上專用的pragma來指明自己的意圖,由此編譯器可以自動將程式進行並行化,並在必要之處加入同步互斥
OpenCV3入門教程(一)基礎知識
------韋訪 20181011 1、概述 想學習影象處理,不管是機器學習也好,深度學習也好,不會點OpenCV好像有點說不過去吧?所以,現在開始OpenCV的學習。 2、讀寫圖片 先從圖片的讀寫開始,opencv讀取圖片的函式是imread,預設情況下,imrea
Python-matplotlib-入門教程(一)-基礎圖表繪製
0.摘要 本教程主要介紹使用python第三方庫matplotlib繪製各種統計圖表,教程從簡單到複雜,逐步遞進。 本章主要介紹常見圖表的繪製方法,並以儘可能簡單的方式實現,主要以突出函式功能為目的,防止讀者被複雜的引數分散了注意力。鑑於函式的引數的相似性,讀者只需要知道引數的含義並結合he
Git-入門教程(一)-什麼是Git
0.摘要 本文主要介紹Git的概念、特點和功能。 1.什麼是Git 分散式版本控制系統。 所謂分散式,指的是每一位開發者都能在各自的機器上擁有一個完整的版本庫。每個開發者通過克隆(git clone)操作,可以從中央伺服器上拷貝一個完整的Git倉庫到本地機器上,整