1. 程式人生 > >基於高版本Lucene的中文分詞器(IK分詞器)的DEMO

基於高版本Lucene的中文分詞器(IK分詞器)的DEMO

注意

為了大家方便,我沒有遮蔽資料庫,專案中用的資料來源請各位碼友不要亂搞~謝謝

緣起

日前專案中需要用到Lucene.且需要中文分詞,看了下IK分詞器,但是IK分詞器貌似只支援到lucene的3.X。後期的版本就不支援了,在網上找了一部分資料,自己寫了一個demo.因為中間有不少坑,所以特此記錄。

關於Demo

demo採用的lucene的版本是6.4.0。demo基於springmvc+JPA+mybatis+maven。Lucene的高版本和低版本的API不盡相同。而且不同版本基於的IK分詞器也不盡相同。使用過程需注意

專案所需JAR包

IKAnalyzer分詞器因為不支援高版本的,故借鑑網上的資料寫了一個支援高版本Lucene的分詞器。

下載連結。下載下來之後需要把jar包加入到你本地或者伺服器的庫檔案中,關於怎麼把本地jar包加入到maven庫中,請移步(外鏈可能失效,失效請百度怎麼把本地jar包加入到maven庫中)

    <dependency>
      <groupId>org.apache.lucene</groupId>
      <artifactId>lucene-core</artifactId>
      <version>6.4.0</version>
    </dependency>
    
    <dependency>
      <groupId>com.seaboat</groupId>
      <artifactId>IKAnalyzer</artifactId>
      <version>6.4.0</version>
    </dependency>

因為只是一個簡單的demo.所以並沒有加入Lucene的關鍵字高亮顯示包,如果需要高亮顯示則還需要加入

<!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-highlighter -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-highlighter</artifactId>
    <version>6.4.0</version>
</dependency>

示例程式碼

篇幅所限,本處只列出關鍵程式碼

user(對應資料庫表)

public class User implements Serializable {
    @Id
    @Column(name = "id")
    private Integer id;
    @Column(name = "userName")
    private String userName;
    @Column(name = "password")
    private String password;
    @Column(name = "name")
    private String name;

}

DataModel(lucene關鍵,採集的資料模型類)

public class DataModel {
    private String id;
    private String name;
}

DataManageService(資料採集類,關鍵程式碼)

package com.bxoon.service;

import com.bxoon.dao.UserDao;
import com.bxoon.domain.DataModel;
import com.bxoon.domain.User;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

/**
 * 資料管理Service
 */
@Service
public class DataManageService {

    @Autowired
    UserDao userDao;

    /**
     * 資料採集
     */
    private List<DataModel> getData(){
        List<User> list = userDao.findAll();
        List<DataModel> dataModelList = new ArrayList<>(list.size());
        for (User user:list){
            DataModel dataModel = new DataModel();
            dataModel.setId(user.getId()+"");
            dataModel.setName(user.getName());
            dataModelList.add(dataModel);
        }
        return dataModelList;
    }

    /**
     * 建立索引
     */
    public void createIndex(){
        try {
            List<DataModel> dataModelList = getData();
            List<Document> documentList = new ArrayList<>();
            dataModelList.forEach(e -> {
                Document document = new Document();
                Field idField = new TextField("id", e.getId(), Field.Store.YES);
                Field nameFiled = new TextField("name", e.getName(), Field.Store.YES);
                document.add(idField);
                document.add(nameFiled);
                documentList.add(document);
            });

            IKAnalyzer ikAnalyzer = new IKAnalyzer();
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(ikAnalyzer);
            File indexFile = new File("E:\\LuceneRepo\\");
            Path path = indexFile.toPath();
            Directory directory = FSDirectory.open(path);
            IndexWriter writer = new IndexWriter(directory, indexWriterConfig);
            writer.addDocuments(documentList);
            writer.commit();
            writer.close();
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

    public void indexSearch(){
        try {
            // 建立query物件
            // 使用QueryParser搜尋時,需要指定分詞器,搜尋時的分詞器要和索引時的分詞器一致
            // 第一個引數:預設搜尋的域的名稱
//            QueryParser parser = new QueryParser("name", new IKAnalyzer());
//            parser.setAllowLeadingWildcard(true);
//            Query query = parser.parse("name:張");
            Term aTerm = new Term("name", "張三");
            Query query = new TermQuery(aTerm);

            // 建立IndexSearcher
            // 指定索引庫的地址
            File indexFile = new File("E:\\LuceneRepo");
            Path path = indexFile.toPath();
            Directory directory = FSDirectory.open(path);
            DirectoryReader ireader = DirectoryReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(ireader);

            // 通過searcher來搜尋索引庫
            // 第二個引數:指定需要顯示的頂部記錄的N條
            TopDocs topDocs = searcher.search(query, 100);
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (ScoreDoc scoreDoc:scoreDocs){
                int scoreDocId = scoreDoc.doc;
                Document document = searcher.doc(scoreDocId);
                System.out.println("id:"+document.get("id"));
                System.out.println("name:"+document.get("name"));
            }
            directory.close();
            ireader.close();
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}

copy IK分詞器的配置檔案進專案的resources目錄

IK分詞器需要兩個配置檔案。IKAnalyzer.cfg.xml,stopword.dic。我看網上的部分教程沒有,不知道為什麼反正我是需要,不然會不成功。本想給出連結直接下載,考慮到還要上傳百度網盤什麼的太麻煩了,所以直接給出內容。需要的朋友直接copy到檔案裡面然後改成對應的名字,然後copy到專案的resource目錄下就可以了。

IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
<properties>  
	<comment>IK Analyzer 擴充套件配置</comment>
	<!--使用者可以在這裡配置自己的擴充套件字典 
	<entry key="ext_dict">ext.dic;</entry> 
	-->
	<!--使用者可以在這裡配置自己的擴充套件停止詞字典-->
	<entry key="ext_stopwords">stopword.dic;</entry> 
	
</properties>

stopword.dic

a
an
and
are
as
at
be
but
by
for
if
in
into
is
it
no
not
of
on
or
such
that
the
their
then
there
these
they
this
to
was
will
with

檢視索引庫內容

分詞完成了之後會在程式碼裡面配置的路徑下生產幾個檔案,就是分詞之後形成的索引庫檔案,類似於
在這裡插入圖片描述
可以通過Lucene庫檔案檢視工具Luke檢視庫的內容。LUKE的版本也需要跟Lucene的版本差不多,否則無法檢視。下面給出下載連結
連結:https://pan.baidu.com/s/1TqIN25lA90eUUnvu2ghDyA
提取碼:22lw
下載下來如果你是window系統那直接執行luke.bat檔案,開啟介面後選擇你的lucene的索引庫檔案的路徑就可以查看了。
在這裡插入圖片描述
如果庫裡面看不到內容,那可能是版本不對,也可能是你的分詞沒有成功。

寫在最後

東西寫的比較簡單,中間也是有很多坑。建議看我git上的一個LuceneDemo.

中間有幾個坑是需要注意的,比如copy IK分詞器的配置檔案那一步,網上的部分教程沒有。
另外,GIT上的部分碼友寫的IK分詞器在使用maven命令mvn install打包過程中會遺失main2012.dic這個檔案,導致專案中使用會有問題。需要在打好了包之後手動copy進去。

參考

https://blog.csdn.net/wangyangzhizhou/article/details/71487030