Lucene第一篇【介紹Lucene、快速入門】

什麼是Lucene??

Lucene是apache軟件基金會發布的一個開放源代碼的全文檢索引擎工具包,由資深全文檢索專家Doug Cutting所撰寫,它是一個全文檢索引擎的架構,提供了完整的建立索引和查詢索引,以及部分文本分析的引擎,Lucene的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便在目標系統中實現全文檢索的功能,或者是以此爲基礎創建起完整的全文檢索引擎,Lucene在全文檢索領域是一個經典的祖先,如今不少檢索引擎都是在其基礎上建立的,思想是相通的。java

Lucene是根據關健字來搜索的文本搜索工具,只能在某個網站內部搜索文本內容,不能跨網站搜索程序員

既然談到了網站內部的搜索,那麼咱們就談談咱們熟悉的百度、google那些搜索引擎又是基於什麼搜索的呢….算法

這裏寫圖片描述

這裏寫圖片描述

從圖上已經看得很清楚,baidu、google等搜索引擎實際上是經過網絡爬蟲的程序來進行搜索的數據庫


爲何咱們要用Lucene?

在介紹Lucene的時候,咱們已經說了:Lucene又不是搜索引擎,僅僅是在網站內部進行文本的搜索。那咱們爲何要學他呢???apache

咱們以前編寫納稅服務系統的時候,其實就已經使用過SQL來進行站內的搜索..markdown

既然SQL能作的功能,咱們還要學Lucene,爲何呢???網絡

咱們來看看咱們用SQL來搜索的話,有什麼缺點:架構

  • (1)SQL只能針對數據庫表搜索,不能直接針對硬盤上的文本搜索
  • (2)SQL沒有相關度排名
  • (3)SQL搜索結果沒有關健字高亮顯示
  • (4)SQL須要數據庫的支持,數據庫自己須要內存開銷較大,例如:Oracle
  • (5)SQL搜索有時較慢,尤爲是數據庫不在本地時,超慢,例如:Oracle

這裏寫圖片描述

咱們來看看在baidu中搜索Lucene爲關鍵字搜索出的內容是怎麼樣的:工具

這裏寫圖片描述

以上所說的,咱們若是使用SQL的話,是作不到的。所以咱們就學習Lucene來幫咱們在站內根據文本關鍵字來進行搜索數據學習


咱們若是網站須要根據關鍵字來進行搜索,可使用SQL,也可使用Lucene…那麼咱們Lucene和SQL是同樣的,都是在持久層中編寫代碼的。。

這裏寫圖片描述

快速入門

接下來,咱們就講解怎麼使用Lucene了…..在講解Lucene的API以前,咱們首先來說講Lucene存放的到底是什麼內容…咱們的SQL使用的是數據庫中的內存,在硬盤中爲DBF文件…那麼咱們Lucene內部又是什麼東西呢??

Lucene中存的就是一系列的二進制壓縮文件和一些控制文件,它們位於計算機的硬盤上,
這些內容統稱爲索引庫,索引庫有二部份組成:

  • (1)原始記錄
    • 存入到索引庫中的原始文本,例如:我是鍾福成
  • (2)詞彙表
    • 按照必定的拆分策略(即分詞器)將原始記錄中的每一個字符拆開後,存入一個供未來搜索的表

也就是說:Lucene存放數據的地方咱們一般稱之爲索引庫,索引庫又分爲兩部分組成:原始記錄和詞彙表….

原始記錄和詞彙表

當咱們想要把數據存到索引庫的時候,咱們首先存入的是將數據存到原始記錄上面去….

又因爲咱們給用戶使用的時候,用戶使用的是關鍵字來進行查詢咱們的具體記錄。所以,咱們須要把咱們原始存進的數據進行拆分!將拆分出來的數據存進詞彙表中

詞彙表就是相似於咱們在學Oracle中的索引表,拆分的時候會給出對應的索引值。

一旦用戶根據關鍵字來進行搜索,那麼程序就先去查詢詞彙表中有沒有該關鍵字,若是有該關鍵字就定位到原始記錄表中,將符合條件的原始記錄返回給用戶查看

咱們查看如下的圖方便理解:

這裏寫圖片描述

到了這裏,有人可能就會疑問:難道原始記錄拆分的數據都是一個一個漢字進行拆分的嗎??而後在詞彙表中不就有不少的關鍵字了???

其實,咱們在存到原始記錄表中的時候,能夠指定咱們使用哪一種算法來將數據拆分,存到詞彙表中…..咱們的圖是Lucene的標準分詞算法,一個一個漢字進行拆分。咱們可使用別的分詞算法,兩個兩個拆分或者其餘的算法。

編寫第一個Lucene程序

首先,咱們來導入Lucene的必要開發包:

  • lucene-core-3.0.2.jar【Lucene核心】
  • lucene-analyzers-3.0.2.jar【分詞器】
  • lucene-highlighter-3.0.2.jar【Lucene會將搜索出來的字,高亮顯示,提示用戶】
  • lucene-memory-3.0.2.jar【索引庫優化策略】

建立User對象,User對象封裝了數據….

/** * Created by ozc on 2017/7/12. */
public class User {


    private String id ;
    private String userName;
    private String sal;

    public User() {

    }
    public User(String id, String userName, String sal) {
        this.id = id;
        this.userName = userName;
        this.sal = sal;
    }
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getSal() {
        return sal;
    }

    public void setSal(String sal) {
        this.sal = sal;
    }
}

咱們想要使用Lucene來查詢出站內的數據,首先咱們得要有個索引庫吧!因而咱們先建立索引庫,將咱們的數據存到索引庫中

建立索引庫的步驟:

  • 1)建立JavaBean對象
  • 2)建立Docment對象
  • 3)將JavaBean對象全部的屬性值,均放到Document對象中去,屬性名能夠和JavaBean相同或不一樣
  • 4)建立IndexWriter對象
  • 5)將Document對象經過IndexWriter對象寫入索引庫中
  • 6)關閉IndexWriter對象
@Test
    public void createIndexDB() throws Exception {

        //把數據填充到JavaBean對象中
        User user = new User("1", "鍾福成", "將來的程序員");

        //建立Document對象【導入的是Lucene包下的Document對象】
        Document document = new Document();

        //將JavaBean對象全部的屬性值,均放到Document對象中去,屬性名能夠和JavaBean相同或不一樣


        /** * 向Document對象加入一個字段 * 參數一:字段的關鍵字 * 參數二:字符的值 * 參數三:是否要存儲到原始記錄表中 * YES表示是 * NO表示否 * 參數四:是否須要將存儲的數據拆分到詞彙表中 * ANALYZED表示拆分 * NOT_ANALYZED表示不拆分 * * */
        document.add(new Field("id", user.getId(), Field.Store.YES, Field.Index.ANALYZED));
        document.add(new Field("userName", user.getUserName(), Field.Store.YES, Field.Index.ANALYZED));
        document.add(new Field("sal", user.getSal(), Field.Store.YES, Field.Index.ANALYZED));

        //建立IndexWriter對象
        //目錄指定爲E:/createIndexDB
        Directory directory = FSDirectory.open(new File("E:/createIndexDB"));

        //使用標準的分詞算法對原始記錄表進行拆分
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);

        //LIMITED默認是1W個
        IndexWriter.MaxFieldLength maxFieldLength = IndexWriter.MaxFieldLength.LIMITED;
        /** * IndexWriter將咱們的document對象寫到硬盤中 * * 參數一:Directory d,寫到硬盤中的目錄路徑是什麼 * 參數二:Analyzer a, 以何種算法來對document中的原始記錄表數據進行拆分紅詞彙表 * 參數三:MaxFieldLength mfl 最多將文本拆分出多少個詞彙 * * */
        IndexWriter indexWriter = new IndexWriter(directory, analyzer, maxFieldLength);

        //將Document對象經過IndexWriter對象寫入索引庫中
        indexWriter.addDocument(document);

        //關閉IndexWriter對象
        indexWriter.close();

    }

這裏寫圖片描述

程序執行完,咱們就會在硬盤中見到咱們的索引庫。

這裏寫圖片描述

那咱們如今是不知道記錄是否真真正正存儲到索引庫中的,由於咱們看不見。索引庫存放的數據放在cfs文件下,咱們也是不能打開cfs文件的

因而,咱們如今用一個關鍵字,把索引庫的數據讀取。看看讀取數據是否成功。

根據關鍵字查詢索引庫中的內容:

  • 1)建立IndexSearcher對象
  • 2)建立QueryParser對象
  • 3)建立Query對象來封裝關鍵字
  • 4)用IndexSearcher對象去索引庫中查詢符合條件的前100條記錄,不足100條記錄的以實際爲準
  • 5)獲取符合條件的編號
  • 6)用indexSearcher對象去索引庫中查詢編號對應的Document對象
  • 7)將Document對象中的全部屬性取出,再封裝回JavaBean對象中去,並加入到集合中保存,以備將之用
@Test
    public void findIndexDB() throws Exception {

        /** * 參數一: IndexSearcher(Directory path)查詢以xxx目錄的索引庫 * * */
        Directory directory = FSDirectory.open(new File("E:/createIndexDB"));
        //建立IndexSearcher對象
        IndexSearcher indexSearcher = new IndexSearcher(directory);

        //建立QueryParser對象
        /** * 參數一: Version matchVersion 版本號【和上面是同樣的】 * 參數二:String f,【要查詢的字段】 * 參數三:Analyzer a【使用的拆詞算法】 * */
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
        QueryParser queryParser = new QueryParser(Version.LUCENE_30, "userName", analyzer);

        //給出要查詢的關鍵字
        String keyWords = "鍾";

        //建立Query對象來封裝關鍵字
        Query query = queryParser.parse(keyWords);

        //用IndexSearcher對象去索引庫中查詢符合條件的前100條記錄,不足100條記錄的以實際爲準
        TopDocs topDocs = indexSearcher.search(query, 100);

        //獲取符合條件的編號

        for (int i = 0; i < topDocs.scoreDocs.length; i++) {

            ScoreDoc scoreDoc = topDocs.scoreDocs[i];
            int no = scoreDoc.doc;
            //用indexSearcher對象去索引庫中查詢編號對應的Document對象
            Document document = indexSearcher.doc(no);

            //將Document對象中的全部屬性取出,再封裝回JavaBean對象中去
            String id = document.get("id");
            String userName = document.get("userName");
            String sal = document.get("sal");

            User user = new User(id, userName, sal);
            System.out.println(user);

        }

這裏寫圖片描述

效果:

這裏寫圖片描述


進一步說明Lucene代碼

咱們的Lucene程序就是大概這麼一個思路:將JavaBean對象封裝到Document對象中,而後經過IndexWriter把document寫入到索引庫中。當用戶須要查詢的時候,就使用IndexSearcher從索引庫中讀取數據,找到對應的Document對象,從而解析裏邊的內容,再封裝到JavaBean對象中讓咱們使用

這裏寫圖片描述

相關文章
相關標籤/搜索