全文檢索技術lucene的demo

meimengxing發表於2022-10-27

lucene是一個基於Java的全文檢索庫,使用lucene能夠建立全文索引和搜尋,當資料量比較大的時候,比起傳統的順序搜尋,索引搜尋速度提升會非常明顯。很多搜尋引擎例如Elasticsearch 和 solor 都是以lucene為核心的。

全文檢索指的是,提前對文章或者文件中的每一個詞建立索引,索引中包含該詞在文章中出現的位置和次數,當使用者查詢時,根據事先建立好的索引進行查詢,並返回查詢結果。

這種建立索引,在透過搜尋索引返回資料的方式就叫全文檢索。

優點:

  • 查詢準確高。
  • 查詢速度快,不會隨著資料量的增大而變得越來越慢。

缺點:

  • 索引會佔據磁碟儲存空間

應用場景:

  • 大量資料檢索(貼吧,論壇,淘寶,京東)
  • 搜尋引擎 (google、baidu)

Lucene是Apache旗下的一個開源全文檢索引擎庫,提供了完整了查詢引擎和索引引擎。使用lucene可以在系統中實現全文檢索功能,或者以此為基礎構建一個全文檢索引擎。
Lucene不是現成的搜尋引擎產品,但確可以用來製作搜尋引擎產品。

假如要為資料庫中的資料庫建立全文檢索,大致的步驟如下:先獲取到資料庫中的資料庫,對這批資料建立索引,索引儲存在索引庫中。當使用者查詢時,對索引庫的索引進行查詢,從而找到相對應的資料。

重點在於建立索引的這部分。建立索引時需要將資料構建為Lucene中的 文件物件,並對文件物件進行分析,最後建立索引

程式碼步驟如下:

1.建立索引:

  • 獲取資料
  • 建立Document文件物件()
  • 建立分詞器
  • 建立Directory物件,宣告索引庫儲存位置
  • 建立IndexWriterConfig配置資訊類
  • 建立IndexWriter寫入物件
  • 把Document寫入到索引庫中(底層自動建立索引)
  • 關閉寫入流

POJO類省略–

Dao層省略–

pom.xml 中引入依賴:

<!--lucene核心-->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>7.7.2</version>
        </dependency>
        <!--lucene分詞器-->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>7.7.2</version>
        </dependency>
        <!--lucene查詢解析-->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>7.7.2</version>
        </dependency>
        <!--中文分詞器-->
        <dependency>
            <groupId>org.wltea.ik-analyzer</groupId>
            <artifactId>ik-analyzer</artifactId>
            <version>8.1.0</version>
        </dependency>

測試類
建立索引:

/*### 
建立索引:
*   獲取資料
*   建立Document文件物件()
*   建立分詞器
*   建立Directory物件,宣告索引庫儲存位置
*   建立IndexWriterConfig配置資訊類
*   建立IndexWriter寫入物件
*   把Document寫入到索引庫中(底層自動建立索引)
*/
//建立全部索引
    @Test
    public void createIndex() throws IOException {


        //獲取原始資料
        List<YxStoreProduct> skuList = yxStoreProductRepository.findAll();
        //建立分詞器
        Analyzer analyzerIK = new IKAnalyzer();
        //建立文件物件集合
        List<Document> documents =new ArrayList<>();
        for (YxStoreProduct sku : skuList) {
            Document document = new Document();
            document.add(new StringField("id",sku.getId().toString(), Field.Store.YES));
            document.add(new TextField("store_name",sku.getStoreName(), Field.Store.YES));
            document.add(new TextField("storeInfo",sku.getStoreInfo(), Field.Store.YES));
            document.add(new TextField("price",sku.getPrice().toString(), Field.Store.YES));
            documents.add(document);
        }
        Directory directory = FSDirectory.open(Paths.get("D:\\lucene\\indexDir"));
        Directory directory2 = FSDirectory.open(Paths.get(msgIndex));


        //建立IndexWriterConfig物件,寫入索引需要的配置
        IndexWriterConfig config = new IndexWriterConfig(analyzerIK);
        //建立IndexWriter寫入物件
        IndexWriter indexWriter = new IndexWriter(directory2,config);
        indexWriter.addDocuments(documents);
        indexWriter.close();
    }

搜尋索引:

@Test
    public void searchIndex() throws Exception {
        //建立分詞器
        Analyzer analyzerIK = new IKAnalyzer();
        //建立Directory流物件,宣告索引庫位置
        Directory directory = FSDirectory.open(Paths.get("D:\\yshop\\msgindex"));
        //建立搜尋解析器 第一個引數是指定預設搜尋的field
        QueryParser queryParser = new QueryParser("store_name",analyzerIK);
        //建立搜尋物件 
        Query query = queryParser.parse("商品");
        //建立索引讀取物件
        IndexReader reader = DirectoryReader.open(directory);
        //建立索引搜尋物件
        IndexSearcher searcher = new IndexSearcher(reader);


        //使用索引搜尋物件執行搜尋
        TopDocs topDocs =searcher.search(query,10);
        System.out.println("查詢到的資料總條數是:"+topDocs.totalHits);
        //獲取查詢結果集
        ScoreDoc[] docs = topDocs.scoreDocs;


        //解析結果集:
        for(ScoreDoc scoreDoc:docs){
            //拿到文件id
            int docID = scoreDoc.doc;
            Document doc =searcher.doc(docID);


            System.out.println("=============================");
            System.out.println("docID:"+docID);
            System.out.println("id:"+doc.get("id"));
            System.out.println("store_name:"+doc.get("store_name"));
            System.out.println("storeInfo:"+doc.get("storeInfo"));
            System.out.println("price:"+doc.get("price"));
        }
        reader.close();
    }

結果展示:

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章