lucene索引的增刪改查/lucene索引維護

lucene供了完整的查詢引擎和索引引擎,像商城之類的很多網站都會使用,包括大數據也在使用類似的工具,所以很有必要了解決一下,文章 主要是測試了lucene的索引創建、刪除、更新及queryParser查詢索引的方式。

創建lucene數據庫,並創建book表,SQL語句內容如下:

USE `lucene`;

DROP TABLE IF EXISTS `book`;

CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) COLLATE utf8_bin DEFAULT NULL,
  `price` double DEFAULT NULL,
  `pic` varchar(100) COLLATE utf8_bin DEFAULT NULL,
  `description` varchar(5000) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


insert  into `book`(`id`,`name`,`price`,`pic`,`description`) values (1,'java',11.23,'121323.jpg','給你推薦一個寫得非常用心的Java基礎教程:Java入門基礎教程 | 天碼營這個教程將Java的入門基礎知識貫穿在一個實例中,逐步深入,可以幫助你快速進入Java編程的世界。萬事開頭難,逐步跟着這個教程走一遍,對Java應該就會有一種入門的感覺了。然後再去學習更高級的主題,或者更深入地學習其中的某些知識點。第1課 Java開發環境安裝與配置 第2課 第一個Java程序 第3課 面向對象基礎 第4課 基本數據類型 第5課 運算符 第6課 字符串操作 第7課 程序的控制流 第8課 靜態變量與靜態方法 第9課 Java集合 第10課 封裝與繼承 第11課 抽象類與接口 第12課 異常處理 第13課 綜合實例 第14課 Eclipse的安裝與使用\n\n作者:David\n鏈接:https://www.zhihu.com/question/25255189/answer/86898400\n來源:知乎\n著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。'),(2,'lucene solx ',12.55,'56465465.jpg','Lucene是apache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此爲基礎建立起完整的全文檢索引擎。Lucene是一套用於全文檢索和搜尋的開源程式庫,由Apache軟件基金會支持和提供。Lucene提供了一個簡單卻強大的應用程式接口,能夠做全文索引和搜尋。在Java開發環境裏Lucene是一個成熟的免費開源工具。就其本身而言,Lucene是當前以及最近幾年最受歡迎的免費Java信息檢索程序庫。人們經常提到信息檢索程序庫,雖然與搜索引擎有關,但不應該將信息檢索程序庫與搜索引擎相混淆。[1] '),(3,'java spring mybatis Struts2 springMVC hibernate',99.25,'6546545656.jpg','輕量——從大小與開銷兩方面而言Spring都是輕量的。完整的Spring框架可以在一個大小隻有1MB多的JAR文件裏發佈。並且Spring所需的處理開銷也是微不足道的。此外,Spring是非侵入式的:典型地,Spring應用中的對象不依賴於Spring的特定類。\r\n控制反轉——Spring通過一種稱作控制反轉(IoC)的技術促進了低耦合。當應用了IoC,一個對象依賴的其它對象會通過被動的方式傳遞進來,而不是這個對象自己創建或者查找依賴對象。你可以認爲IoC與JNDI相反——不是對象從容器中查找依賴,而是容器在對象初始化時不等對象請求就主動將依賴傳遞給它。\r\n面向切面——Spring提供了面向切面編程的豐富支持,允許通過分離應用的業務邏輯與系統級服務(例如審計(auditing)和事務(transaction)管理)進行內聚性的開發。應用對象只實現它們應該做的——完成業務邏輯——僅此而已。它們並不負責(甚至是意識)其它的系統級關注點,例如日誌或事務支持。\r\n容器——Spring包含並管理應用對象的配置和生命週期,在這個意義上它是一種容器,你可以配置你的每個bean如何被創建——基於一個可配置原型(prototype),你的bean可以創建一個單獨的實例或者每次需要時都生成一個新的實例——以及它們是如何相互關聯的。然而,Spring不應該被混同於傳統的重量級的EJB容器,它們經常是龐大與笨重的,難以使用。\r\n框架——Spring可以將簡單的組件配置、組合成爲複雜的應用。在Spring中,應用對象被聲明式地組合,典型地是在一個XML文件裏。Spring也提供了很多基礎功能(事務管理、持久化框架集成等等),將應用邏輯的開發留給了你。\r\nMVC——Spring的作用是整合,但不僅僅限於整合,Spring 框架可以被看做是一個企業解決方案級別的框架。客戶端發送請求,服務器控制器(由DispatcherServlet實現的)完成請求的轉發,控制器調用一個用於映射的類HandlerMapping,該類用於將請求映射到對應的處理器來處理請求。HandlerMapping 將請求映射到對應的處理器Controller(相當於Action)在Spring 當中如果寫一些處理器組件,一般實現Controller 接口,在Controller 中就可以調用一些Service 或DAO 來進行數據操作 ModelAndView 用於存放從DAO 中取出的數據,還可以存放響應視圖的一些數據。 如果想將處理結果返回給用戶,那麼在Spring 框架中還提供一個視圖組件ViewResolver,該組件根據Controller 返回的標示,找到對應的視圖,將響應response 返回給用戶。\r\n所有Spring的這些特徵使你能夠編寫更乾淨、更可管理、並且更易於測試的代碼。它們也爲Spring中的各種模塊提供了基礎'),(4,'天氣你好啊哦咯看i我看',22.22,'365456564.jpg','G蛋白偶聯受體(G Protein-Coupled Receptors,GPCRs)是一肽類膜蛋白受體的統稱。這類受體的共同點是其立體結構中都有七個跨膜α螺旋,且其肽鏈的C端和連接第5和第6個跨膜螺旋的胞內環上都有G蛋白(鳥苷酸結合蛋白)的結合位點。目前爲止,研究顯示G蛋白偶聯受體只見於真核生物之中,而且參與了很多細胞信號轉導過程。在這些過程中,G蛋白偶聯受體能結合細胞周圍環境中的化學物質並激活細胞內的一系列信號通路,最終引起細胞狀態的改變。已知的與G蛋白偶聯受體結合的配體包括氣味,費洛蒙,激素,神經遞質,趨化因子等等。這些配體可以是小分子的糖類,脂質,多肽,也可以是蛋白質等生物大分子。一些特殊的G蛋白偶聯受體也可以被非化學性的刺激源激活,例如在感光細胞中的視紫紅質可以被光所激活。與G蛋白偶聯受體相關的疾病爲數衆多,並且大約40%的現代藥物都以G蛋白偶聯受體作爲靶點。'),(5,'愛奇藝',54.25,'adsfasdfa.jpg','愛奇藝,中國視頻行業領先者。2010年4月22日正式上線,秉承“悅享品質”的品牌口號,積極推動產品、技術、內容、營銷等全方位創新,爲用戶\r\n愛奇藝VIP代言人\r\n愛奇藝VIP代言人(6張)\r\n 提供豐富、高清、流暢的專業視頻體驗,致力於讓人們平等、便捷地獲得更多、更好的視頻。截止到2015年7月,愛奇藝已成功構建了包含電商、遊戲、電影票等業務在內、連接人與服務的視頻商業生態,引領視頻網站商業模式的多元化發展。[1] \r\n愛奇藝品質、青春、時尚的品牌調性深入人心,網羅了中國最廣大的年輕用戶羣體。愛奇藝打造涵蓋電影、電視劇、綜藝、動漫在內的十餘種類型的中國最大正版視頻內容庫,並通過“愛奇藝出品”戰略的持續推動,讓“純網內容”進入真正意義上的全類別、高品質時代。同時,作爲中國付費用戶規模最大的視頻網站,愛奇藝倡導“輕奢新主義”的VIP會員理念,主張人們對高品質生活細節的追求,堅持爲廣大VIP會員提供專屬的海量精品內容,極致的視聽體驗,以及獨有的線下會員服務。[1] \r\n2014年,愛奇藝在全球範圍內率先建立起首個基於搜索和視頻數據理解人類行爲的視頻大腦——愛奇藝大腦,用大數據指導內容的製作、生產、運營、消費。並通過強大的雲計算能力,以及領先行業的帶寬儲備,和全球最龐大的視頻分發網絡,爲用戶提供更好的視頻服務。在技術與內容雙核驅動的新體驗營銷時代,愛奇藝創造性地提出了“iJOY悅享營銷”客戶服務價值觀和方法論。通過多屏觸點、創意內容、技術優化、互動參與、實現購買等路徑全面提升ROI,讓客戶享受到創新營銷帶來的成功與快樂。[1] \r\n未來,愛奇藝將在多元化的內容儲備、個性化的產品體驗、定製化營銷服務領域繼續發力,引領視頻體驗革命。不斷提升連接人與服務的能力,更好的改變人們的生活。[');

導入jar包,其中數據庫的驅動我導入的是Mysql的,junit包有些自帶,如果帶的有可不導入

這裏寫圖片描述

創建Book實體類

package com.ckinghan.bean;

import java.io.Serializable;

public class Book implements Serializable {

    // 圖書ID
    private Integer id;
    // 圖書名稱
    private String name;
    // 圖書價格
    private Float price;
    // 圖書圖片
    private String pic;
    // 圖書描述
    private String description;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Float getPrice() {
        return price;
    }
    public void setPrice(Float price) {
        this.price = price;
    }
    public String getPic() {
        return pic;
    }
    public void setPic(String pic) {
        this.pic = pic;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    @Override
    public String toString() {
        return "Book [id=" + id + ", name=" + name + ", price=" + price + ", pic=" + pic + ", description="
                + description + "]";
    }

}

創建BookDao接口,並創建queryBooks方法

import java.util.List;

import com.ckinghan.bean.Book;

public interface BookDao {

    /**
     * 查詢所有的BOOK內容
     * @創建時間:2017年10月7日16:15:10
     */
    public List<Book> queryBooks();


}

創建BookDao的實現類BookDaoImpl

package com.ckinghan.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.ckinghan.bean.Book;

public class BookDaoImpl implements BookDao {

    @Override
    public List<Book> queryBooks() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        List<Book> books = new ArrayList<Book>();
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/lucene","root","root");
            String sql = "select * from book";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                Book book = new Book();
                book.setId(resultSet.getInt("id"));
                book.setName(resultSet.getString("name"));
                book.setPic(resultSet.getString("pic"));
                book.setPrice(resultSet.getFloat("price"));
                book.setDescription(resultSet.getString("description"));
                books.add(book);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return books;
    }

}

創建測試文件:

package com.ckinghan.lucene;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

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.Field.Store;
import org.apache.lucene.document.FloatField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
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;
import org.apache.lucene.util.Version;
import org.junit.Test;

import com.ckinghan.bean.Book;
import com.ckinghan.dao.BookDao;
import com.ckinghan.dao.BookDaoImpl;

public class TwoCreateIndex {

    /**
     * 創建並在指定的位置寫入lucene索引文件 
     * @創建時間:2017年10月7日20:58:47
     */
    @Test
    public void createIndex() throws IOException {
        // 查詢數據
        BookDao bookDao = new BookDaoImpl();
        List<Book> books = bookDao.queryBooks();

        // 定義一個Document集合
        List<Document> documents = new ArrayList<>();
        // 定義document對象
        Document document;

        // 遍歷查詢出來的數據
        for (Book book : books) {
            // 實例化document對象
            document = new Document();

            // 不進行分詞,只進行索引、存儲
            Field id = new StringField("id", book.getId().toString(), Store.YES);

            // 進行分詞、索引、存儲
            Field name = new TextField("name", book.getName(), Store.YES);

            // 對數值類型(float/double/int/long)不進行分詞,只進行索引、存儲
            Field price = new FloatField("price", book.getPrice(), Store.YES);

            // 不進行分詞、索引,只存儲
            Field pic = new StoredField("pic", book.getPic());

            // 進行分詞、索引,但不存儲
            Field description = new TextField("description", book.getDescription(), Store.NO);

            // 將Field放到document對象中
            document.add(id);
            document.add(name);
            document.add(price);
            document.add(pic);
            document.add(description);

            // 將document放到documents集合中
            documents.add(document);
        }

        // 創建一個標準分詞對象
        Analyzer analyzer = new StandardAnalyzer();
        // 索引庫的位置
        Directory directory = FSDirectory.open(new File("D:" + File.separator + "lucene_index" + File.separator));
        // 索引序列化的配置
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
        // 創建索引序列化(寫入流)對象
        IndexWriter writer = new IndexWriter(directory, config);

        // 將documents對象循環寫入到指定的索引目錄 中
        for (Document doc : documents) {
            writer.addDocument(doc);
        }

        // 關閉流對象
        writer.close();

    }

    /**
     * 通過指定的lucene索引目錄查詢指定的數據 @創建時間:2017年10月7日21:14:30
     */
    @Test
    public void readerIndex() throws ParseException, IOException {
        // 創建QueryParser對象,並指定要查詢的索引域及分詞對象
        QueryParser queryParser = new QueryParser("name", new StandardAnalyzer());
        // 創建Query對象,指定查詢條件
        Query query = queryParser.parse("name:java OR string");

        // 指定要查詢的lucene索引目錄,必須與存儲的索引目錄一致
        Directory directory = FSDirectory.open(new File("D:" + File.separator + "lucene_index" + File.separator));
        // 通過指定的查詢目錄文件地址創建IndexReader流對象
        IndexReader reader = DirectoryReader.open(directory);
        // 通過IndexReader流對象創建IndexSearcher
        IndexSearcher searcher = new IndexSearcher(reader);

        // 執行查詢語句,獲取返回的TopDocs對象(參數中的100爲取出的數據條數)
        TopDocs search = searcher.search(query, 100);

        // 獲取查詢關鍵字獲得的數據總數
        int totalHits = search.totalHits;
        System.out.println("通過查詢條件總共查詢到的數據量爲:" + totalHits);
        System.out.println();

        // 獲取查詢到的數據
        ScoreDoc[] scoreDocs = search.scoreDocs;

        for (ScoreDoc doc : scoreDocs) {
            // 獲取查詢到的索引ID
            int docId = doc.doc;

            // 根據索引查詢數據
            Document document = searcher.doc(docId);

            // 輸出查詢到的數據
            System.out.println("ID數據爲:" + document.get("id"));
            System.out.println("name數據爲:" + document.get("name"));
            System.out.println("price數據爲:" + document.get("price"));
            System.out.println("pic數據爲:" + document.get("pic"));
            System.out.println("description數據爲:" + document.get("description"));
            System.out.println("******************************");
            System.out.println();
            System.out.println();
        }

        // 關閉流
        reader.close();
    }

    public void queryIndex(String id) throws IOException, ParseException {
        Analyzer analyzer = new StandardAnalyzer();
        // 創建指定查詢域、分詞對象創建QueryParser對象
        QueryParser parser = new QueryParser("id", analyzer);
        // 指定查詢條件,創建query對象
        Query query = parser.parse(new StringBuilder("id:").append(id).toString());
        Directory directory = FSDirectory.open(new File("D:" + File.separator + "lucene_index" + File.separator));
        // 創建reader流對象,打開指定的lucene索引目錄
        IndexReader reader = DirectoryReader.open(directory);
        // 通過創建的流對象創建查詢對象searcher
        IndexSearcher searcher = new IndexSearcher(reader);
        // 通過查詢對象查詢指定條件的數據
        TopDocs topDocs = searcher.search(query, 10);
        // 獲取查詢的數據總量
        int totalHits = topDocs.totalHits;
        // 將查詢返回的索引數據賦值給scoreDocs對象
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;

        // 如果查詢的數據不存在,輸出提示信息
        if (scoreDocs == null || scoreDocs.length == 0) {
            System.out.println("未查詢到ID爲" + id + "的數據,刪除ID爲" + id + "的數據成功");
        } else {
            // 如果查詢的數據未刪除成功,則輸出相應的數據
            for (ScoreDoc doc : scoreDocs) {
                // 獲取查詢到的索引id
                int docId = doc.doc;
                // 通過查詢到的索引id查詢索引中對應的文檔域中的內容
                Document document = searcher.doc(docId);
                // 輸出查詢到的數據
                System.out.println("ID數據爲:" + document.get("id"));
                System.out.println("name數據爲:" + document.get("name"));
                System.out.println("price數據爲:" + document.get("price"));
                System.out.println("pic數據爲:" + document.get("pic"));
                System.out.println("description數據爲:" + document.get("description"));
                System.out.println("******************************");
                System.out.println();
                System.out.println();
            }
        }
        // 關閉流對象
        reader.close();
    }

    /**
     * 根據查詢條件刪除lucene索引及文檔數據 @創建時間:2017年10月7日21:58:33
     */
    @Test
    public void deleteIndex() throws IOException, ParseException {
        // 創建分詞對象
        Analyzer analyzer = new StandardAnalyzer();
        // 指定lucene索引目錄地址
        Directory directory = FSDirectory.open(new File("D:" + File.separator + "lucene_index" + File.separator));
        // 創建配置對象
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
        // 通過指定的索引目錄地址、配置對象創建IndexWriter流對象
        IndexWriter writer = new IndexWriter(directory, config);
        // 刪除索引目錄 id = 1的數據
        writer.deleteDocuments(new Term("id", "1"));

        // 清空索引及存檔的所有數據
        // writer.deleteAll();

        // 關閉流對象
        writer.close();

        // 查詢id爲1的數據是否刪除成功
        queryIndex("1");

    }

    /**
     * 更新索引
     * @創建時間:2017年10月7日22:13:07
     */
    @Test
    public void updateIndex() throws IOException, ParseException {
        //創建分詞對象
        Analyzer analyzer = new StandardAnalyzer();
        //指定索引目錄地址
        Directory directory = FSDirectory.open(new File("D:" + File.separator + "lucene_index" + File.separator));
        //創建配置對象
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
        //通過配置、目錄參數創建流對象
        IndexWriter writer = new IndexWriter(directory, config);

        //創建document對象
        Document doc = new Document();
        //添加索引數據到doc對象
        doc.add(new TextField("id", "7", Store.YES));
        //將新添加的doc數據替換索引中已經有的id爲2的數據
        //執行步驟如下:查詢數據--》查詢到或未查詢到--》替換/添加doc數據
        writer.updateDocument(new Term("id", "2"), doc);

        //關閉流
        writer.close();

        // 查詢id爲2的數據是否更改成功,如果更改成功,就沒有了id爲2的數據
        queryIndex("2");

        // 查詢id爲7的數據是否替換寫入索引成功
        queryIndex("7");
    }
}

執行方法createIndex()創建索引效果如下圖所示,已經生成了索引文件。

這裏寫圖片描述

執行方法readerIndex()查詢指定的數據效果如下所示:

通過查詢條件總共查詢到的數據量爲:2

ID數據爲:1
name數據爲:java
price數據爲:11.23
pic數據爲:121323.jpg
description數據爲:null
******************************


ID數據爲:3
name數據爲:java spring mybatis Struts2 springMVC hibernate
price數據爲:99.25
pic數據爲:6546545656.jpg
description數據爲:null
******************************


執行方法deleteIndex() 根據查詢條件刪除lucene索引及文檔數據效果如下所示:

未查詢到ID爲1的數據,刪除ID爲1的數據成功

執行方法updateIndex() 更新索引效果如下所示:

未查詢到ID爲2的數據,刪除ID爲2的數據成功
ID數據爲:7
name數據爲:null
price數據爲:null
pic數據爲:null
description數據爲:null
******************************


發佈了153 篇原創文章 · 獲贊 69 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章