Lucene

1. 本文主要內容

  1. Lucene介紹
  2. 全文檢索流程介紹

    a) 索引流程html

    b) 搜索流程java

  1. Lucene入門程序

    a) 索引實現mysql

    b) 搜索實現git

  1. 分詞器

    a) 分詞介紹github

    b) IK分詞器web

2. 搜索技術理論基礎

2.1. 爲何要學習Lucene

原來的方式實現搜索功能,咱們的搜索流程以下圖:算法

 

上圖就是原始搜索引擎技術,若是用戶比較少並且數據庫的數據量比較小,那麼這種方式實現搜索功能在企業中是比較常見的。spring

可是數據量過多時,數據庫壓力就會變得很大查詢速度會變得很是慢。咱們須要使用更好的解決方案來分擔數據庫壓力。sql

如今的方案(使用Lucene),以下圖  數據庫

 

爲了解決數據庫壓力和速度的問題,咱們的數據庫就變成了索引庫,咱們使用LuceneAPI的來操做服務器上的索引庫。這樣徹底和數據庫進行了隔離。

2.2. 數據查詢方法

2.2.1. 順序掃描法

所謂順序掃描,例如要找內容包含一個字符串的文件,就是一個文檔一個文檔的看,對於每個文檔,從頭看到尾,若是此文檔包含此字符串,則此文檔爲咱們要找的文件,接着看下一個文件,直到掃描完全部的文件。

這種方法是順序掃描方法,數據量大就搜索慢。

 

先搜索文檔、再今後文檔找詞   

2.2.2. 倒排索引

先舉一個栗子    

例如咱們使用新華字典查詢漢字,新華字典有偏旁部首的目錄(索引),咱們查字首先查這個目錄,找到這個目錄中對應的偏旁部首,就能夠經過這個目錄中的偏旁部首找到這個字所在的位置(文檔)。

 

先詞後文檔

如今有兩篇文檔:

Doc1: When in Rome, do as the Romans do.

Doc2: When do you come back from Rome?

 

Lucene會對以上兩篇文檔創建倒排索引

索引結構以下圖:  

 

一、 提取資源中關鍵信息, 創建索引 (目錄)

二、 搜索時,根據關鍵字(目錄),找到資源的位置

 

2.1. 搜索技術應用場景

應用場景

1、 單機軟件的搜索(word中的搜索)

2、 站內搜索 (baidu貼吧、論壇、 京東、 taobao

3、 垂直領域的搜索 (818工做網) 智聯 拉鉤 Boss直  

4、 專業搜索引擎公司 (googlebaidu

3. Lucene介紹  

3.1. 什麼是全文索引(全文檢索)

計算機索引程序經過掃描文章中的每個詞,對每個詞創建一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先創建的索引進行查找,並將查找的結果反饋給用戶的檢索方式

 

先建立索引  再對索引進行搜索的過程叫全文檢索 (全文索引)

 

3.2. 什麼是Lucene   

Luceneapache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。

 

Lucene的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此爲基礎創建起完整的全文檢索引擎。

 

目前已經有不少應用程序的搜索功能是基於 Lucene 的,好比 Eclipse 的幫助系統的搜索功能。Lucene 可以爲文本類型的數據創建索引,因此你只要能把你要索引的數據格式轉化的文本的,Lucene 就能對你的文檔進行索引和搜索。好比你要對一些 HTML 文檔,PDF 文檔進行索引的話你就首先須要把 HTML 文檔和 PDF 文檔轉化成文本格式的,而後將轉化後的內容交給 Lucene 進行索引,而後把建立好的索引文件保存到磁盤或者內存中,最後根據用戶輸入的查詢條件在索引文件上進行查詢。不指定要索引的文檔的格式也使 Lucene 可以幾乎適用於全部的搜索應用程序。

 

l Lucene是一套用於全文檢索和搜尋的開源程式庫,由Apache軟件基金會支 持和提供

l Lucene提供了一個簡單卻強大的應用程式接口,可以作全文索引和搜尋, Java開發環境裏Lucene是一個成熟的免費開放源代碼工具

l Lucene並非現成的搜索引擎產品,但能夠用來製做搜索引擎產品

引擎產品 百度 Lucene作的 原理 倒排索引通用的 語言不是同 Lucene實現倒排索引 (並不必定Lucene實現)

3.3. Lucene與搜索引擎的區別

全文檢索系統是按照全文檢索理論創建起來的用於提供全文檢索服務的軟件系統,包括創建索引、處理查詢返回結果集、增長索引、優化索引結構等功能。例如:百度搜索、eclipse幫助搜索、淘寶網商品搜索等。

 

完整的系統   百度 淘寶  京東  搜索引擎

Lucene 實現此搜索引擎系統的工具包 

搜索引擎是全文檢索技術最主要的一個應用,例如百度。搜索引擎起源於傳統的信息全文檢索理論,即計算機程序經過掃描每一篇文章中的每個詞,創建以詞爲單位的倒排文件,檢索程序根據檢索詞在每一篇文章中出現的頻率和每個檢索詞在一篇文章中出現的機率,對包含這些檢索詞的文章進行排序,最後輸出排序的結果。全文檢索技術是搜索引擎的核心支撐技術。

Lucene和搜索引擎不一樣,Lucene是一套用java或其它語言寫的全文檢索的工具包,爲應用程序提供了不少個api接口去調用,能夠簡單理解爲是一套實現全文檢索的類庫,搜索引擎是一個全文檢索系統,它是一個單獨運行的軟件系統

3.4. Lucene官網

官網: http://lucene.apache.org/

4. Lucene全文檢索的流程 

4.1. 索引和搜索流程圖 

 

1、綠色表示索引過程,對要搜索的原始內容進行索引構建一個索引庫,索引過程包括:

肯定原始內容即要搜索的內容à得到文檔à建立文檔à分析文檔à索引文檔

 

2、紅色表示搜索過程,從索引庫中搜索內容,搜索過程包括:

用戶經過搜索界面à建立查詢à執行搜索,從索引庫搜索à渲染搜索結果

4.2. 索引流程

對文檔索引的過程,將用戶要搜索的文檔內容進行索引,索引存儲在索引庫(index)中。

 

4.2.1. 原始內容

原始內容是指要索引和搜索的內容。

原始內容包括互聯網上的網頁、數據庫中的數據、磁盤上的文件等。

 

4.2.2. 得到文檔(採集數據)

從互聯網上、數據庫、文件系統中等獲取須要搜索的原始信息,這個過程就是信息採集,採集數據的目的是爲了對原始內容進行索引。

 

採集數據分類:

1、對於互聯網上網頁,可使用工具將網頁抓取到本地生成html文件。

2、數據庫中的數據,能夠直接鏈接數據庫讀取表中的數據。

3、文件系統中的某個文件,能夠經過I/O操做讀取文件的內容。

 

Internet上採集信息的軟件一般稱爲爬蟲或蜘蛛,也稱爲網絡機器人,爬蟲訪問互聯網上的每個網頁,將獲取到的網頁內容存儲起來。

Lucene不提供信息採集的類庫,須要本身編寫一個爬蟲程序實現信息採集,也能夠經過一些開源軟件實現信息採集,以下:

Solrhttp://lucene.apache.org/solr solrapache的一個子項目,支持從關係數據庫、xml文檔中提取原始數據。

Nutchhttp://lucene.apache.org/nutch, Nutchapache的一個子項目,包括大規模爬蟲工具,可以抓取和分辨web網站數據。

jsouphttp://jsoup.org/ ),jsoup 是一款Java HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套很是省力的API,可經過DOMCSS以及相似於jQuery的操做方法來取出和操做數據。

 

4.2.3. 建立文檔

獲取原始內容的目的是爲了索引,在索引前須要將原始內容建立成文檔(Document),文檔中包括一個一個的域(Field),域中存儲內容。

這裏咱們能夠將磁盤上的一個文件當成一個documentDocument中包括一些Field,以下圖:

 

注意:每一個Document能夠有多個Field,不一樣的Document能夠有不一樣的Field,同一個Document能夠有相同的Field(域名和域值都相同)

4.2.4. 分析文檔

將原始內容建立爲包含域(Field)的文檔(document),須要再對域中的內容進行分析,分析成爲一個一個的單詞。

 

好比下邊的文檔通過分析以下:

原文檔內容:

Lucene is a Java full-text search engine.  Lucene is not a complete

application, but rather a code library and API that can easily be used

to add search capabilities to applications.

分析後獲得的詞:

lucenejavafullsearchengine。。。。

 

4.2.5. 索引文檔

對全部文檔分析得出的語彙單元進行索引,索引的目的是爲了搜索,最終要實現只搜索被索引的語彙單元從而找到Document(文檔)。

建立索引是對語彙單元索引,經過詞語找文檔,這種索引的結構叫倒排索引結構。

倒排索引結構是根據內容(詞彙)找文檔,以下圖:

 

 

倒排索引結構也叫反向索引結構,包括索引和文檔兩部分,索引即詞彙表,它的規模較小,而文檔集合較大。索引 詞彙表 語彙單元要比搜索文檔集合要快的多。

 

4.3.  搜索流程

搜索就是用戶輸入關鍵字,從索引中進行搜索的過程。根據關鍵字搜索索引,根據索引找到對應的文檔,從而找到要搜索的內容。

4.3.1. 用戶

就是使用搜索的角色,用戶能夠是天然人,也能夠是遠程調用的程序。

 

4.3.2. 用戶搜索界面   Lucene  全文檢索系統

全文檢索系統提供用戶搜索的界面供用戶提交搜索的關鍵字,搜索完成展現搜索結果。以下圖:

 

Lucene不提供製做用戶搜索界面的功能,須要根據本身的需求開發搜索界面。

 

4.3.3. 建立查詢

用戶輸入查詢關鍵字執行搜索以前須要先構建一個查詢對象,查詢對象中能夠指定查詢要查詢關鍵字、要搜索的Field文檔域等,查詢對象會生成具體的查詢語法,好比:

name:lucene表示要搜索name這個Field域中,內容爲「lucene」的文檔。

desc:lucene AND desc:java 表示要搜索即包括關鍵字「lucene」也包括「java」的文檔。

OR

 

4.3.4. 執行搜索

搜索索引過程:

1.根據查詢語法在倒排索引詞典表中分別找出對應搜索詞的索引,從而找到索引所連接的文檔鏈表。

例如搜索語法爲desc:lucene AND desc:java」表示搜索出的文檔中既要包括lucene也要包括java

二、因爲是AND,因此要對包含lucenejava詞語的鏈表進行交集,獲得文檔鏈表應該包括每個搜索詞語

三、獲取文檔中的Field域數據。

 

4.3.5. 渲染結果

以一個友好的界面將查詢結果展現給用戶,用戶根據搜索結果找本身想要的信息,爲了幫助用戶很快找到本身的結果,提供了不少展現的效果,好比搜索結果中將關鍵字高亮顯示,百度提供的快照等。

 

5. Lucene入門

5.1. Lucene準備

Lucene能夠在官網上下載。課程已經準備好了Lucene的文件,咱們使用的是4.10.3版本,文件位置以下圖:

解壓後的效果:

使用這三個文件的jar包,就能夠實現lucene功能

 

5.2. 開發環境

JDK 1.7 Lucene4.8以上,必須使用JDK1.7及以上版本)

IDE eclipse Mars2

數據庫: MySQL  

5.3. 建立Java工程

建立java工程測試便可

5.4. 索引流程

5.4.1. 數據採集

電商網站中,全文檢索的數據源在數據庫中,須要經過jdbc訪問數據庫中book表的內容。

5.4.1.1. 建立pojo

 1 public class Book {
 2 
 3 // 圖書ID
 4 
 5 private Integer id;
 6 
 7 // 圖書名稱
 8 
 9 private String name;
10 
11 // 圖書價格
12 
13 private Float price;
14 
15 // 圖書圖片
16 
17 private String pic;
18 
19 // 圖書描述
20 
21 private String desc;
22 
23 get/set。。。
24 
25 }

5.4.1.2. 建立DAO接口

 1 public interface BookDao {
 2 
 3 /**
 4  * 查詢全部的book數據
 5  *
 6  * @return
 7  */
 8 
 9 List<Book> queryBookList();
10 
11 }

5.4.1.3. 建立DAO接口實現類

使用jdbc實現

 1 public class BookDaoImpl implements BookDao {
 2 
 3 @Override
 4 
 5 public List<Book> queryBookList() {
 6 
 7 // 數據庫連接
 8 
 9 Connection connection = null;
10 
11 // 預編譯statement
12 
13 PreparedStatement preparedStatement = null;
14 
15 // 結果集
16 
17 ResultSet resultSet = null;
18 
19 // 圖書列表
20 
21 List<Book> list = new ArrayList<Book>();
22 
23  
24 
25 try {
26 
27 // 加載數據庫驅動
28 
29 Class.forName("com.mysql.jdbc.Driver");
30 
31 // 鏈接數據庫
32 
33 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/solr", "root", "root");
34 
35 
36 // SQL語句
37 
38 String sql = "SELECT * FROM book";
39 
40 // 建立preparedStatement
41 
42 preparedStatement = connection.prepareStatement(sql);
43 
44 // 獲取結果集
45 
46 resultSet = preparedStatement.executeQuery();
47 
48 // 結果集解析
49 
50 while (resultSet.next()) {
51 
52 Book book = new Book();
53 
54 book.setId(resultSet.getInt("id"));
55 
56 book.setName(resultSet.getString("name"));
57 
58 book.setPrice(resultSet.getFloat("price"));
59 
60 book.setPic(resultSet.getString("pic"));
61 
62 book.setDesc(resultSet.getString("desc"));
63 
64 list.add(book);
65 
66 }
67 
68 } catch (Exception e) {
69 
70 e.printStackTrace();
71 
72 }
73 
74 return list;
75 
76 }
77 
78 }

 

5.4.2. 實現索引流程

  1. 採集數據
  2. 建立Document文檔對象
  3. 建立分析器(分詞器)
  4. 建立IndexWriterConfig配置信息類
  5. 建立Directory對象,聲明索引庫存儲位置
  6. 建立IndexWriter寫入對象
  7. Document寫入到索引庫中
  8. 釋放資源
package com.wxs.text;

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

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import com.wxs.dao.BookDao;
import com.wxs.dao.BookDaoImpl;
import com.wxs.pojo.Book;

/**
*@author 做者: WangXS
*@version 日期: 2018年10月9日 下午4:29:05
*/
public class CreateIndexTest {
    @Test
    public void testCreateIndex() throws Exception {
    //1.採集數據
    BookDao bd = new BookDaoImpl();
    List<Book> bookList = bd.queryBookList();
    //2.建立Document文檔對象
    List<Document> documents = new ArrayList<>();
    for (Book book : bookList) {
        Document document = new Document();
        // Document文檔中添加Field域
        // 圖書Id
        // Store.YES:表示存儲到文檔域中
        document.add(new TextField("id", book.getId().toString(), Store.YES));
        // 圖書名稱
        document.add(new TextField("name", book.getName().toString(), Store.YES));
        // 圖書價格
        document.add(new TextField("price", book.getPrice().toString(), Store.YES));
        // 圖書圖片地址
        document.add(new TextField("pic", book.getPic().toString(), Store.YES));
        // 圖書描述
        document.add(new TextField("desc", book.getDesc().toString(), Store.YES));
        // 把Document放到list中
        documents.add(document);
    }
    //3.建立分析器(分詞器)
    //StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
     IKAnalyzer analyzer = new IKAnalyzer();
    //4.建立IndexWriterConfig配置信息類
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
    //5.建立Directory對象,聲明索引庫存儲位置
    Directory directory = FSDirectory.open(new File("F:\\temp\\index"));
    //6.建立IndexWriter寫入對象
    IndexWriter indexWriter  = new IndexWriter(directory, config);
    //7.把Document寫入到索引庫中
    for (Document document : documents) {
        indexWriter.addDocument(document);
    }
    //8.釋放資源
    indexWriter.close();
    
    }
}

 

 

執行效果:

在文件夾中出現瞭如下文件,表示建立索引成功

 

 

5.4.3. 使用Luke查看索引

Luke做爲Lucene工具包中的一個工具(http://www.getopt.org/luke/),能夠經過界面來進行索引文件的查詢、修改

5.5. 搜索流程

5.5.1. 輸入查詢語句

Lucene能夠經過query對象輸入查詢語句。同數據庫的sql同樣,lucene也有固定的查詢語法:

最基本的有好比:AND, OR, NOT 等(必須大寫

 

舉個栗子:

用戶想找一個desc中包括java關鍵字和lucene關鍵字的文檔。

它對應的查詢語句:desc:java AND desc:lucene

5.5.1.1. 搜索分詞

和索引過程的分詞同樣,這裏要對用戶輸入的關鍵字進行分詞,通常狀況索引和搜索使用的分詞器一致

好比:輸入搜索關鍵字java學習」,分詞後爲java和學習兩個詞,與java和學習有關的內容都搜索出來了,以下:

 

 

5.5.2. 代碼實現

 1. 建立Query搜索對象

 2. 建立Directory流對象,聲明索引庫位置

 3. 建立索引讀取對象IndexReader

 4. 建立索引搜索對象IndexSearcher

 5. 使用索引搜索對象,執行搜索,返回結果集TopDocs

 6. 解析結果集

 7. 釋放資源

 

IndexSearcher搜索方法以下:

方法

說明

indexSearcher.search(query, n)

根據Query搜索,返回評分最高的n條記錄

indexSearcher.search(query, filter, n)

根據Query搜索,添加過濾策略,返回評分最高的n條記錄

indexSearcher.search(query, n, sort)

根據Query搜索,添加排序策略,返回評分最高的n條記錄

indexSearcher.search(booleanQuery, filter, n, sort)

根據Query搜索,添加過濾策略,添加排序策略,返回評分最高的n條記錄

 

代碼實現

 1 package com.wxs.text;
 2 
 3 import java.io.File;
 4 
 5 import org.apache.lucene.analysis.Analyzer;
 6 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 7 import org.apache.lucene.document.Document;
 8 import org.apache.lucene.index.DirectoryReader;
 9 import org.apache.lucene.index.IndexReader;
10 import org.apache.lucene.queryparser.classic.QueryParser;
11 import org.apache.lucene.search.IndexSearcher;
12 import org.apache.lucene.search.Query;
13 import org.apache.lucene.search.ScoreDoc;
14 import org.apache.lucene.search.TopDocs;
15 import org.apache.lucene.store.Directory;
16 import org.apache.lucene.store.FSDirectory;
17 import org.junit.Test;
18 
19 /**
20 *@author 做者: WangXS
21 *@version 日期: 2018年10月10日 下午3:38:00
22 */
23 public class SearchIndexTest {
24     @Test
25     public void testSearchIndex() throws Exception {
26         //1. 建立Query搜索對象
27         // 建立分詞器
28         Analyzer analyzer = new StandardAnalyzer();
29         // 建立搜索解析器,第一個參數:默認Field域,第二個參數:分詞器
30         QueryParser queryParser = new QueryParser("desc", analyzer);
31         Query query = queryParser.parse("desc:java AND lucene");
32         //2. 建立Directory流對象,聲明索引庫位置
33         Directory directory = FSDirectory.open(new File("F:\\temp\\index"));
34         //3. 建立索引讀取對象IndexReader
35         IndexReader indexReader = DirectoryReader.open(directory);
36         //4. 建立索引搜索對象IndexSearcher
37         IndexSearcher search = new IndexSearcher(indexReader);
38         //5. 使用索引搜索對象,執行搜索,返回結果集TopDocs
39         // 第一個參數:搜索對象,第二個參數:返回的數據條數,指定查詢結果最頂部的n條數據返回
40         TopDocs topDocs = search.search(query, 5);
41         System.out.println("查詢到的數據總條數是:" + topDocs.totalHits);
42         //6. 解析結果集
43         ScoreDoc[] scoreDocs = topDocs.scoreDocs;
44             for (ScoreDoc scoreDoc : scoreDocs) {
45                 //獲取文檔
46                 int docId = scoreDoc.doc;
47                 Document doc = search.doc(docId);
48                 System.out.println("=============================");
49                 System.out.println("docID:" + docId);
50                 System.out.println("bookId:" + doc.get("id"));
51                 System.out.println("name:" + doc.get("name"));
52                 System.out.println("price:" + doc.get("price"));
53                 System.out.println("pic:" + doc.get("pic"));
54                 // System.out.println("desc:" + doc.get("desc"));
55             }
56         //7. 釋放資源
57         indexReader.close();    
58     }
59 }

 

6. 分詞器

6.1. 分詞理解

在對Docuemnt中的內容進行索引以前,須要使用分詞器進行分詞 ,分詞的目的是爲了搜索。分詞的主要過程就是先分詞後過濾。

 

分詞:採集到的數據會存儲到document對象的Field域中,分詞就是將DocumentFieldvalue值切分紅一個一個的詞。

過濾:包括去除標點符號過濾、去除停用詞過濾(的、是、aanthe等)、大寫轉小寫、詞的形還原(複數形式轉成單數形參、過去式轉成如今式。。。)等。 

 

 

什麼是停用詞?停用詞是爲節省存儲空間和提升搜索效率,搜索引擎在索引頁面或處理搜索請求時會自動忽略某些字或詞,這些字或詞即被稱爲Stop Words(停用詞)。好比語氣助詞、副詞、介詞、鏈接詞等,一般自身並沒有明確的意義,只有將其放入一個完整的句子中才有必定做用,如常見的「的」、「在」、「是」、「啊」等。

 

對於分詞來講,不一樣的語言,分詞規則不一樣。Lucene做爲一個工具包提供不一樣國家的分詞器,本例子使用StandardAnalyzer它能夠對用英文進行分詞

 

以下是org.apache.lucene.analysis.standard.standardAnalyzer的部分源碼:

 

 1 @Override
 2 
 3   protected TokenStreamComponents createComponents(final String fieldName, final Reader reader) {
 4 
 5     final StandardTokenizer src = new StandardTokenizer(getVersion(), reader);
 6 
 7     src.setMaxTokenLength(maxTokenLength);
 8 
 9     TokenStream tok = new StandardFilter(getVersion(), src);
10 
11     tok = new LowerCaseFilter(getVersion(), tok);
12 
13     tok = new StopFilter(getVersion(), tok, stopwords);
14 
15     return new TokenStreamComponents(src, tok) {
16 
17       @Override
18 
19       protected void setReader(final Reader reader) throws IOException {
20 
21         src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
22 
23         super.setReader(reader);
24 
25       }
26 
27     };
28 
29   }

 

 

Tokenizer就是分詞器,負責將reader轉換爲語彙單元即進行分詞處理,Lucene提供了不少的分詞器,也可使用第三方的分詞,好比IKAnalyzer一箇中文分詞器。

 

TokenFilter是分詞過濾器,負責對語彙單元進行過濾,TokenFilter能夠是一個過濾器鏈兒,Lucene提供了不少的分詞器過濾器,好比大小寫轉換、去除停用詞等。

 

以下圖是語彙單元的生成過程:

 

 

從一個Reader字符流開始,建立一個基於ReaderTokenizer分詞器,通過三個TokenFilter生成語彙單元Tokens

 

好比下邊的文檔通過分析器分析以下:

  • 原文檔內容:

 

  • 分析後獲得的多個語彙單元:

 

6.2. Analyzer使用時機

6.2.1. 索引時使用Analyzer

輸入關鍵字進行搜索,當須要讓該關鍵字與文檔域內容所包含的詞進行匹配時須要對文檔域內容進行分析,須要通過Analyzer分析器處理生成語彙單元(Token)。分析器分析的對象是文檔中的Field域。當Field的屬性tokenized(是否分詞)爲true時會對Field值進行分析,以下圖:

 

對於一些Field能夠不用分析:

1、不做爲查詢條件的內容,好比文件路徑

2、不是匹配內容中的詞而匹配Field的總體內容,好比訂單號、身份證號等。

 

6.2.2. 搜索時使用Analyzer

對搜索關鍵字進行分析和索引分析同樣,使用Analyzer對搜索關鍵字進行分析、分詞處理,使用分析後每一個詞語進行搜索。好比:搜索關鍵字:spring web ,通過分析器進行分詞,得出:spring  web拿詞去索引詞典表查找 ,找到索引連接到Document,解析Document內容。

對於匹配總體Field域的查詢能夠在搜索時不分析,好比根據訂單號、身份證號查詢等。

注意:搜索使用的分析器要和索引使用的分析器一致

 

6.3. 中文分詞器

6.3.1. 什麼是中文分詞器

學過英文的都知道,英文是以單詞爲單位的,單詞與單詞之間以空格或者逗號句號隔開。因此對於英文,咱們能夠簡單以空格判斷某個字符串是否爲一個單詞,好比I love Chinalove China很容易被程序區分開來。

 

而中文則以字爲單位,字又組成詞,字和詞再組成句子。中文「我愛中國」就不同了,電腦不知道「中國」是一個詞語仍是「愛中」是一個詞語。

 

把中文的句子切分紅有意義的詞,就是中文分詞,也稱切詞。我愛中國,分詞的結果是:我、愛、中國。

 

6.3.2. Lucene自帶中文分詞器

l StandardAnalyzer

單字分詞:就是按照中文一個字一個字地進行分詞。如:我愛中國
效果:

 

l CJKAnalyzer

二分法分詞:按兩個字進行切分。如:中國人,效果:中國「國人」

 

上邊兩個分詞器沒法知足需求。

l SmartChineseAnalyzer

對中文支持較好,但擴展性差,擴展詞庫,禁用詞庫和同義詞庫等很差處理

 

6.4. 第三方中文分詞器

l paoding: 庖丁解牛最新版在 https://code.google.com/p/paoding/ 中最多支持Lucene 3.0,且最新提交的代碼在 2008-06-03,在svn中最新也是2010年提交,已通過時,不予考慮。

 

l mmseg4j:最新版已從 https://code.google.com/p/mmseg4j/ 移至 https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代碼是2014年6月,從09年~14年一共有:18個版本,也就是一年幾乎有3個大小版本,有較大的活躍度,用了mmseg算法。

 

l IK-analyzer 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10從2006年12月推出1.0版開始, IKAnalyzer已經推出了4個大版本。最初,它是以開源項目Luence爲應用主體的,結合詞典分詞和文法分析算法的中文分詞組件。從3.0版本開 始,IK發展爲面向Java的公用分詞組件,獨立於Lucene項目,同時提供了對Lucene的默認優化實現。在2012版本中,IK實現了簡單的分詞 歧義排除算法,標誌着IK分詞器從單純的詞典分詞向模擬語義分詞衍化。 可是也就是2012年12月後沒有在更新。

 

l ansj_seg:最新版本在 https://github.com/NLPchina/ansj_seg tags僅有1.1版本,從2012年到2014年更新了大小6次,可是做者本人在2014年10月10日說明:「可能我之後沒有精力來維護ansj_seg了」,如今由」nlp_china」管理。2014年11月有更新。並未說明是否支持Lucene,是一個由CRF(條件隨機場)算法所作的分詞算法。

 

l imdict-chinese-analyzer:最新版在 https://code.google.com/p/imdict-chinese-analyzer/  最新更新也在2009年5月,下載源碼,不支持Lucene 4.10 。是利用HMM(隱馬爾科夫鏈)算法。

 

l Jcseg:最新版本在git.oschina.net/lionsoul/jcseg,支持Lucene 4.10,做者有較高的活躍度。利用mmseg算法。

 

6.5. 使用中文分詞器IKAnalyzer

IKAnalyzer繼承LuceneAnalyzer抽象類,使用IKAnalyzerLucene自帶的分析器方法同樣,將Analyzer測試代碼改成IKAnalyzer測試中文分詞效果。

 

若是使用中文分詞器ik-analyzer,就須要在索引和搜索程序中使用一致的分詞器:IK-analyzer

6.5.1. 添加jar

6.5.2. 修改分詞器代碼

6.6. 擴展中文詞庫

若是想配置擴展詞和停用詞,就建立擴展詞的文件和停用詞的文件。

注意不要用window自帶的記事本保存擴展詞文件和停用詞文件那樣的話格式中是含有bom

ikanalyzer包中拷貝配置文件

拷貝資源文件夾中

 

IKAnalyzer.cfg.xml配置文件

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
 4 
 5 <properties>  
 6 
 7 <comment>IK Analyzer 擴展配置</comment>
 8 
 9 <!--用戶能夠在這裏配置本身的擴展字典 -->
10 
11 <entry key="ext_dict">ext.dic;</entry> 
12 
13  
14 
15 <!--用戶能夠在這裏配置本身的擴展中止詞字典-->
16 
17 <entry key="ext_stopwords">stopword.dic;</entry> 
18 
19  
20 
21 </properties>

中文詞庫,添加新詞的地方

stopword.dic是存放停用詞的地方 

相關文章
相關標籤/搜索