日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lucene 第一天

發(fā)布時(shí)間:2023/12/31 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lucene 第一天 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

?

?

Lucene/Solr

?

第一天

?

1.?課程計(jì)劃

  • Lucene介紹
  • 全文檢索流程介紹
  • a)?索引流程

    b)?搜索流程

  • Lucene入門程序
  • a)?索引實(shí)現(xiàn)

    b)?搜索實(shí)現(xiàn)

  • 分詞器
  • a)?分詞介紹

    b)?IK分詞器

    ?

    ?

    ?

    ?

    ?

    2.?搜索介紹

    2.1.?實(shí)現(xiàn)搜索的方案

    原來的方式實(shí)現(xiàn)搜索功能,我們的搜索流程如下圖:

    ?

    上圖就是原始搜索引擎技術(shù),如果用戶比較少而且數(shù)據(jù)庫的數(shù)據(jù)量比較小,那么這種方式實(shí)現(xiàn)搜索功能在企業(yè)中是比較常見的。

    ?

    但是數(shù)據(jù)量過多時(shí),數(shù)據(jù)庫壓力就會(huì)變得很大查詢速度會(huì)變得非常慢。我們需要使用更好的解決方案來分擔(dān)數(shù)據(jù)庫壓力。

    ?

    現(xiàn)在的方案(使用Lucene),如下圖

    ?

    為了解決數(shù)據(jù)庫壓力和速度的問題,我們的數(shù)據(jù)庫就變成了索引庫,我們使用LuceneAPI的來操作服務(wù)器上的索引庫。這樣完全和數(shù)據(jù)庫進(jìn)行了隔離。

    ?

    ?

    ?

    2.2.?數(shù)據(jù)查詢方法

    2.2.1.?順序掃描法

    所謂順序掃描,例如要找內(nèi)容包含一個(gè)字符串的文件,就是一個(gè)文檔一個(gè)文檔的看,對(duì)于每一個(gè)文檔,從頭看到尾,如果此文檔包含此字符串,則此文檔為我們要找的文件,接著看下一個(gè)文件,直到掃描完所有的文件。

    這種方法是順序掃描方法,數(shù)據(jù)量大就搜索慢。

    ?

    2.2.2.?倒排索引

    先舉一個(gè)栗子:

    例如我們使用新華字典查詢漢字,新華字典有偏旁部首的目錄(索引),我們查字首先查這個(gè)目錄,找到這個(gè)目錄中對(duì)應(yīng)的偏旁部首,就可以通過這個(gè)目錄中的偏旁部首找到這個(gè)字所在的位置(文檔)。

    ?

    ?

    現(xiàn)在有兩篇文檔:

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

    Doc2: When do you come back from Rome?

    ?

    Lucene會(huì)對(duì)以上兩篇文檔建立倒排索引

    索引結(jié)構(gòu)如下圖:

    ?

    1、?提取資源中關(guān)鍵信息, 建立索引 (目錄)

    2、?搜索時(shí),根據(jù)關(guān)鍵字(目錄),找到資源的位置

    ?

    ?

    1.1.?搜索技術(shù)應(yīng)用場景

    應(yīng)用場景

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

    2、 站內(nèi)搜索 (baidu貼吧、論壇、 京東、 taobao

    3、 垂直領(lǐng)域的搜索 (818工作網(wǎng))

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

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    3.?Lucene介紹

    3.1.?什么是全文索引

    計(jì)算機(jī)索引程序通過掃描文章中的每一個(gè)詞,對(duì)每一個(gè)詞建立一個(gè)索引,指明該詞在文章中出現(xiàn)的次數(shù)和位置,當(dāng)用戶查詢時(shí),檢索程序就根據(jù)事先建立的索引進(jìn)行查找,并將查找的結(jié)果反饋給用戶的檢索方式

    ?

    3.2.?什么是Lucene

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

    ?

    Lucene的目的是為軟件開發(fā)人員提供一個(gè)簡單易用的工具包,以方便的在目標(biāo)系統(tǒng)中實(shí)現(xiàn)全文檢索的功能,或者是以此為基礎(chǔ)建立起完整的全文檢索引擎。

    ?

    目前已經(jīng)有很多應(yīng)用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的幫助系統(tǒng)的搜索功能。Lucene 能夠?yàn)槲谋绢愋偷臄?shù)據(jù)建立索引,所以你只要能把你要索引的數(shù)據(jù)格式轉(zhuǎn)化的文本的,Lucene 就能對(duì)你的文檔進(jìn)行索引和搜索。比如你要對(duì)一些 HTML 文檔,PDF 文檔進(jìn)行索引的話你就首先需要把 HTML 文檔和 PDF 文檔轉(zhuǎn)化成文本格式的,然后將轉(zhuǎn)化后的內(nèi)容交給 Lucene 進(jìn)行索引,然后把創(chuàng)建好的索引文件保存到磁盤或者內(nèi)存中,最后根據(jù)用戶輸入的查詢條件在索引文件上進(jìn)行查詢。不指定要索引的文檔的格式也使 Lucene 能夠幾乎適用于所有的搜索應(yīng)用程序。

    ?

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

    l?Lucene提供了一個(gè)簡單卻強(qiáng)大的應(yīng)用程式接口,能夠做全文索引和搜尋, 在Java開發(fā)環(huán)境里L(fēng)ucene是一個(gè)成熟的免費(fèi)開放源代碼工具

    l?Lucene并不是現(xiàn)成的搜索引擎產(chǎn)品,但可以用來制作搜索引擎產(chǎn)品

    ?

    ?

    3.3.?Lucene與搜索引擎的區(qū)別

    全文檢索系統(tǒng)是按照全文檢索理論建立起來的用于提供全文檢索服務(wù)的軟件系統(tǒng),包括建立索引、處理查詢返回結(jié)果集、增加索引、優(yōu)化索引結(jié)構(gòu)等功能。例如:百度搜索、eclipse幫助搜索、淘寶網(wǎng)商品搜索等。

    ?

    搜索引擎是全文檢索技術(shù)最主要的一個(gè)應(yīng)用,例如百度。搜索引擎起源于傳統(tǒng)的信息全文檢索理論,即計(jì)算機(jī)程序通過掃描每一篇文章中的每一個(gè)詞,建立以詞為單位的倒排文件,檢索程序根據(jù)檢索詞在每一篇文章中出現(xiàn)的頻率和每一個(gè)檢索詞在一篇文章中出現(xiàn)的概率,對(duì)包含這些檢索詞的文章進(jìn)行排序,最后輸出排序的結(jié)果。全文檢索技術(shù)是搜索引擎的核心支撐技術(shù)。

    ?

    Lucene和搜索引擎不同,Lucene是一套用java或其它語言寫的全文檢索的工具包,為應(yīng)用程序提供了很多個(gè)api接口去調(diào)用,可以簡單理解為是一套實(shí)現(xiàn)全文檢索的類庫,搜索引擎是一個(gè)全文檢索系統(tǒng),它是一個(gè)單獨(dú)運(yùn)行的軟件系統(tǒng)

    ?

    3.4.?Lucene官網(wǎng)

    官網(wǎng): http://lucene.apache.org/?

    ?

    4.?Lucene全文檢索的流程

    4.1.?索引和搜索流程圖

    ?

    ?

    1、綠色表示索引過程,對(duì)要搜索的原始內(nèi)容進(jìn)行索引構(gòu)建一個(gè)索引庫,索引過程包括:

    確定原始內(nèi)容即要搜索的內(nèi)容à獲得文檔à創(chuàng)建文檔à分析文檔à索引文檔

    ?

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

    用戶通過搜索界面à創(chuàng)建查詢à執(zhí)行搜索,從索引庫搜索à渲染搜索結(jié)果

    4.2.?索引流程

    對(duì)文檔索引的過程,將用戶要搜索的文檔內(nèi)容進(jìn)行索引,索引存儲(chǔ)在索引庫(index)中。

    ?

    4.2.1.?原始內(nèi)容

    原始內(nèi)容是指要索引和搜索的內(nèi)容。

    原始內(nèi)容包括互聯(lián)網(wǎng)上的網(wǎng)頁、數(shù)據(jù)庫中的數(shù)據(jù)、磁盤上的文件等。

    ?

    4.2.2.?獲得文檔(采集數(shù)據(jù))

    從互聯(lián)網(wǎng)上、數(shù)據(jù)庫、文件系統(tǒng)中等獲取需要搜索的原始信息,這個(gè)過程就是信息采集,采集數(shù)據(jù)的目的是為了對(duì)原始內(nèi)容進(jìn)行索引。

    ?

    采集數(shù)據(jù)分類:

    1、對(duì)于互聯(lián)網(wǎng)上網(wǎng)頁,可以使用工具將網(wǎng)頁抓取到本地生成html文件。

    2、數(shù)據(jù)庫中的數(shù)據(jù),可以直接連接數(shù)據(jù)庫讀取表中的數(shù)據(jù)。

    3、文件系統(tǒng)中的某個(gè)文件,可以通過I/O操作讀取文件的內(nèi)容。

    ?

    Internet上采集信息的軟件通常稱為爬蟲或蜘蛛,也稱為網(wǎng)絡(luò)機(jī)器人,爬蟲訪問互聯(lián)網(wǎng)上的每一個(gè)網(wǎng)頁,將獲取到的網(wǎng)頁內(nèi)容存儲(chǔ)起來。

    Lucene不提供信息采集的類庫,需要自己編寫一個(gè)爬蟲程序?qū)崿F(xiàn)信息采集,也可以通過一些開源軟件實(shí)現(xiàn)信息采集,如下:

    Solrhttp://lucene.apache.org/solr solrapache的一個(gè)子項(xiàng)目,支持從關(guān)系數(shù)據(jù)庫、xml文檔中提取原始數(shù)據(jù)。

    Nutchhttp://lucene.apache.org/nutch, Nutchapache的一個(gè)子項(xiàng)目,包括大規(guī)模爬蟲工具,能夠抓取和分辨web網(wǎng)站數(shù)據(jù)。

    jsoup(http://jsoup.org/?),jsoup 是一款Java HTML解析器,可直接解析某個(gè)URL地址、HTML文本內(nèi)容。它提供了一套非常省力的API,可通過DOMCSS以及類似于jQuery的操作方法來取出和操作數(shù)據(jù)。

    ?

    4.2.3.?創(chuàng)建文檔

    獲取原始內(nèi)容的目的是為了索引,在索引前需要將原始內(nèi)容創(chuàng)建成文檔(Document),文檔中包括一個(gè)一個(gè)的域(Field),域中存儲(chǔ)內(nèi)容。

    這里我們可以將磁盤上的一個(gè)文件當(dāng)成一個(gè)documentDocument中包括一些Field,如下圖:

    ?

    ?

    注意:每個(gè)Document可以有多個(gè)Field,不同的Document可以有不同的Field,同一個(gè)Document可以有相同的Field(域名和域值都相同)

    4.2.4.?分析文檔

    將原始內(nèi)容創(chuàng)建為包含域(Field)的文檔(document),需要再對(duì)域中的內(nèi)容進(jìn)行分析,分析成為一個(gè)一個(gè)的單詞。

    ?

    比如下邊的文檔經(jīng)過分析如下:

    原文檔內(nèi)容:

    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.?索引文檔

    對(duì)所有文檔分析得出的語匯單元進(jìn)行索引,索引的目的是為了搜索,最終要實(shí)現(xiàn)只搜索被索引的語匯單元從而找到Document(文檔)。

    ?

    創(chuàng)建索引是對(duì)語匯單元索引,通過詞語找文檔,這種索引的結(jié)構(gòu)叫倒排索引結(jié)構(gòu)。

    ?

    倒排索引結(jié)構(gòu)是根據(jù)內(nèi)容(詞匯)找文檔,如下圖:

    ?

    ?

    ?

    倒排索引結(jié)構(gòu)也叫反向索引結(jié)構(gòu),包括索引和文檔兩部分,索引即詞匯表,它的規(guī)模較小,而文檔集合較大。

    ?

    4.3.?搜索流程

    搜索就是用戶輸入關(guān)鍵字,從索引中進(jìn)行搜索的過程。根據(jù)關(guān)鍵字搜索索引,根據(jù)索引找到對(duì)應(yīng)的文檔,從而找到要搜索的內(nèi)容。

    ?

    4.3.1.?用戶

    就是使用搜索的角色,用戶可以是自然人,也可以是遠(yuǎn)程調(diào)用的程序。

    ?

    4.3.2.?用戶搜索界面

    全文檢索系統(tǒng)提供用戶搜索的界面供用戶提交搜索的關(guān)鍵字,搜索完成展示搜索結(jié)果。如下圖:

    ?

    Lucene不提供制作用戶搜索界面的功能,需要根據(jù)自己的需求開發(fā)搜索界面。

    ?

    4.3.3.?創(chuàng)建查詢

    用戶輸入查詢關(guān)鍵字執(zhí)行搜索之前需要先構(gòu)建一個(gè)查詢對(duì)象,查詢對(duì)象中可以指定查詢要查詢關(guān)鍵字、要搜索的Field文檔域等,查詢對(duì)象會(huì)生成具體的查詢語法,比如:

    name:lucene表示要搜索name這個(gè)Field域中,內(nèi)容為“lucene”的文檔。

    desc:lucene AND desc:java 表示要搜索既包括關(guān)鍵字“lucene”也包括“java”的文檔。

    ?

    4.3.4.?執(zhí)行搜索

    搜索索引過程:

    1.根據(jù)查詢語法在倒排索引詞典表中分別找出對(duì)應(yīng)搜索詞的索引,從而找到索引所鏈接的文檔鏈表。

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

    ?

    ?

    2、由于是AND,所以要對(duì)包含lucenejava詞語的鏈表進(jìn)行交集,得到文檔鏈表應(yīng)該包括每一個(gè)搜索詞語

    ?

    3、獲取文檔中的Field域數(shù)據(jù)。

    ?

    4.3.5.?渲染結(jié)果

    以一個(gè)友好的界面將查詢結(jié)果展示給用戶,用戶根據(jù)搜索結(jié)果找自己想要的信息,為了幫助用戶很快找到自己的結(jié)果,提供了很多展示的效果,比如搜索結(jié)果中將關(guān)鍵字高亮顯示,百度提供的快照等。

    ?

    5.?Lucene入門

    5.1.?Lucene準(zhǔn)備

    Lucene可以在官網(wǎng)上下載。課程已經(jīng)準(zhǔn)備好了Lucene的文件,我們使用的是4.10.3版本,文件位置如下圖:

    ?

    解壓后的效果:

    ?

    使用這三個(gè)文件的jar包,就可以實(shí)現(xiàn)lucene功能

    ?

    本教程使用的數(shù)據(jù)是MySQL數(shù)據(jù)庫的數(shù)據(jù),所以還需要MySQL的連接包

    學(xué)員編寫的時(shí)候,也可以直接復(fù)制準(zhǔn)備好的jar包,位置如下圖:

    ?

    5.2.?開發(fā)環(huán)境

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

    IDE eclipse Mars2

    數(shù)據(jù)庫: MySQL

    ?

    數(shù)據(jù)庫腳本位置如下圖:

    ?

    ?

    ?

    導(dǎo)入到MySQL效果如下圖:

    ?

    ?

    5.3.?創(chuàng)建Java工程

    創(chuàng)建java工程測試即可,效果如下:

    ?

    ?

    ?

    5.4.?索引流程

    5.4.1.?數(shù)據(jù)采集

    在電商網(wǎng)站中,全文檢索的數(shù)據(jù)源在數(shù)據(jù)庫中,需要通過jdbc訪問數(shù)據(jù)庫中book表的內(nèi)容。

    5.4.1.1.?創(chuàng)建pojo

    public?class?Book {

    // 圖書ID

    private?Integer id;

    // 圖書名稱

    private?String name;

    // 圖書價(jià)格

    private?Float price;

    // 圖書圖片

    private?String pic;

    // 圖書描述

    private?String desc;

    get/set。。。

    }

    ?

    5.4.1.2.?創(chuàng)建DAO接口

    public?interface?BookDao {

    ?

    /**

    ?* 查詢所有的book數(shù)據(jù)

    ?*

    ?* @return

    ?*/

    List<Book> queryBookList();

    }

    ?

    5.4.1.3.?創(chuàng)建DAO接口實(shí)現(xiàn)類

    使用jdbc實(shí)現(xiàn)

    public?class?BookDaoImpl implements?BookDao {

    ?

    @Override

    public?List<Book> queryBookList() {

    // 數(shù)據(jù)庫鏈接

    Connection connection?= null;

    // 預(yù)編譯statement

    PreparedStatement preparedStatement?= null;

    // 結(jié)果集

    ResultSet resultSet?= null;

    // 圖書列表

    List<Book> list?= new?ArrayList<Book>();

    ?

    try?{

    // 加載數(shù)據(jù)庫驅(qū)動(dòng)

    Class.forName("com.mysql.jdbc.Driver");

    // 連接數(shù)據(jù)庫

    connection?= DriverManager.getConnection("jdbc:mysql://localhost:3306/solr", "root", "root");

    ?

    // SQL語句

    String sql?= "SELECT * FROM book";

    // 創(chuàng)建preparedStatement

    preparedStatement?= connection.prepareStatement(sql);

    // 獲取結(jié)果集

    resultSet?= preparedStatement.executeQuery();

    // 結(jié)果集解析

    while?(resultSet.next()) {

    Book book?= new?Book();

    book.setId(resultSet.getInt("id"));

    book.setName(resultSet.getString("name"));

    book.setPrice(resultSet.getFloat("price"));

    book.setPic(resultSet.getString("pic"));

    book.setDesc(resultSet.getString("desc"));

    list.add(book);

    }

    } catch?(Exception e) {

    e.printStackTrace();

    }

    ?

    return?list;

    }

    }

    ?

    5.4.2.?實(shí)現(xiàn)索引流程

  • 采集數(shù)據(jù)
  • 創(chuàng)建Document文檔對(duì)象
  • 創(chuàng)建分析器(分詞器)
  • 創(chuàng)建IndexWriterConfig配置信息類
  • 創(chuàng)建Directory對(duì)象,聲明索引庫存儲(chǔ)位置
  • 創(chuàng)建IndexWriter寫入對(duì)象
  • Document寫入到索引庫中
  • 釋放資源
  • public?class?CreateIndexTest {

    @Test

    public?void?testCreateIndex() throws?Exception {

    // 1. 采集數(shù)據(jù)

    BookDao bookDao?= new?BookDaoImpl();

    List<Book> bookList?= bookDao.queryBookList();

    ?

    // 2. 創(chuàng)建Document文檔對(duì)象

    List<Document> documents?= new?ArrayList<>();

    for?(Book book?: bookList) {

    Document document?= new?Document();

    ?

    // Document文檔中添加Field域

    // 圖書Id

    // Store.YES:表示存儲(chǔ)到文檔域中

    document.add(new?TextField("id", book.getId().toString(), Store.YES));

    // 圖書名稱

    document.add(new?TextField("name", book.getName().toString(), Store.YES));

    // 圖書價(jià)格

    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. 創(chuàng)建Analyzer分詞器,分析文檔,對(duì)文檔進(jìn)行分詞

    Analyzer analyzer?= new?StandardAnalyzer();

    ?

    // 4. 創(chuàng)建Directory對(duì)象,聲明索引庫的位置

    Directory directory?= FSDirectory.open(new?File("C:/itcast/lucene/index"));

    ?

    // 5. 創(chuàng)建IndexWriteConfig對(duì)象,寫入索引需要的配置

    IndexWriterConfig config?= new?IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);

    ?

    // 6.創(chuàng)建IndexWriter寫入對(duì)象

    IndexWriter indexWriter?= new?IndexWriter(directory, config);

    ?

    // 7.寫入到索引庫,通過IndexWriter添加文檔對(duì)象document

    for?(Document doc?: documents) {

    indexWriter.addDocument(doc);

    }

    ?

    // 8.釋放資源

    indexWriter.close();

    }

    }

    ?

    執(zhí)行效果:

    在文件夾中出現(xiàn)了以下文件,表示創(chuàng)建索引成功

    ?

    ?

    ?

    5.4.3.?使用Luke查看索引

    Luke作為Lucene工具包中的一個(gè)工具(http://www.getopt.org/luke/),可以通過界面來進(jìn)行索引文件的查詢、修改

    luke所在位置如下圖:

    ?

    ?

    ?

    打開Luke方法:打開cmd命令行運(yùn)行命令:java -jar lukeall-4.10.3.jar

    打開后,使用如下圖:

    ?

    ?

    下圖是索引域的展示效果:

    ?

    ?

    下圖是文檔域展示效果

    ?

    ?

    ?

    5.5.?搜索流程

    5.5.1.?輸入查詢語句

    Lucene可以通過query對(duì)象輸入查詢語句。同數(shù)據(jù)庫的sql一樣,lucene也有固定的查詢語法:

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

    ?

    舉個(gè)栗子:

    用戶想找一個(gè)desc中包括java關(guān)鍵字和lucene關(guān)鍵字的文檔。

    它對(duì)應(yīng)的查詢語句:desc:java?AND desc:lucene

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    如下圖是使用luke搜索的例子:

    ?

    ?

    ?

    5.5.1.1.?搜索分詞

    和索引過程的分詞一樣,這里要對(duì)用戶輸入的關(guān)鍵字進(jìn)行分詞,一般情況索引和搜索使用的分詞器一致。

    比如:輸入搜索關(guān)鍵字java學(xué)習(xí)”,分詞后為java和學(xué)習(xí)兩個(gè)詞,與java和學(xué)習(xí)有關(guān)的內(nèi)容都搜索出來了,如下:

    ?

    ?

    ?

    5.5.2.?代碼實(shí)現(xiàn)

    ?1. 創(chuàng)建Query搜索對(duì)象

    ?2. 創(chuàng)建Directory流對(duì)象,聲明索引庫位置

    ?3. 創(chuàng)建索引讀取對(duì)象IndexReader

    ?4. 創(chuàng)建索引搜索對(duì)象IndexSearcher

    ?5. 使用索引搜索對(duì)象,執(zhí)行搜索,返回結(jié)果集TopDocs

    ?6. 解析結(jié)果集

    ?7. 釋放資源

    ?

    IndexSearcher搜索方法如下:

    方法

    說明

    indexSearcher.search(query, n)

    根據(jù)Query搜索,返回評(píng)分最高的n條記錄

    indexSearcher.search(query, filter, n)

    根據(jù)Query搜索,添加過濾策略,返回評(píng)分最高的n條記錄

    indexSearcher.search(query, n, sort)

    根據(jù)Query搜索,添加排序策略,返回評(píng)分最高的n條記錄

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

    根據(jù)Query搜索,添加過濾策略,添加排序策略,返回評(píng)分最高的n條記錄

    ?

    代碼實(shí)現(xiàn)

    public?class?SearchIndexTest {

    @Test

    public?void?testSearchIndex() throws?Exception {

    // 1. 創(chuàng)建Query搜索對(duì)象

    // 創(chuàng)建分詞器

    Analyzer analyzer?= new?StandardAnalyzer();

    // 創(chuàng)建搜索解析器,第一個(gè)參數(shù):默認(rèn)Field域,第二個(gè)參數(shù):分詞器

    QueryParser queryParser?= new?QueryParser("desc", analyzer);

    ?

    // 創(chuàng)建搜索對(duì)象

    Query query?= queryParser.parse("desc:java AND lucene");

    ?

    // 2. 創(chuàng)建Directory流對(duì)象,聲明索引庫位置

    Directory directory?= FSDirectory.open(new?File("C:/itcast/lucene/index"));

    ?

    // 3. 創(chuàng)建索引讀取對(duì)象IndexReader

    IndexReader reader?= DirectoryReader.open(directory);

    ?

    // 4. 創(chuàng)建索引搜索對(duì)象

    IndexSearcher searcher?= new?IndexSearcher(reader);

    ?

    // 5. 使用索引搜索對(duì)象,執(zhí)行搜索,返回結(jié)果集TopDocs

    // 第一個(gè)參數(shù):搜索對(duì)象,第二個(gè)參數(shù):返回的數(shù)據(jù)條數(shù),指定查詢結(jié)果最頂部的n條數(shù)據(jù)返回

    TopDocs topDocs?= searcher.search(query, 10);

    System.out.println("查詢到的數(shù)據(jù)總條數(shù)是:"?+ topDocs.totalHits);

    // 獲取查詢結(jié)果集

    ScoreDoc[] docs?= topDocs.scoreDocs;

    ?

    // 6. 解析結(jié)果集

    for?(ScoreDoc scoreDoc?: docs) {

    // 獲取文檔

    int?docID?= scoreDoc.doc;

    Document doc?= searcher.doc(docID);

    ?

    System.out.println("=============================");

    System.out.println("docID:"?+ docID);

    System.out.println("bookId:"?+ doc.get("id"));

    System.out.println("name:"?+ doc.get("name"));

    System.out.println("price:"?+ doc.get("price"));

    System.out.println("pic:"?+ doc.get("pic"));

    // System.out.println("desc:" + doc.get("desc"));

    }

    // 7. 釋放資源

    reader.close();

    }

    }

    ?

    ?

    ?

    ?

    ?

    6.?分詞器

    6.1.?分詞理解

    在對(duì)Docuemnt中的內(nèi)容進(jìn)行索引之前,需要使用分詞器進(jìn)行分詞 ,分詞的目的是為了搜索。分詞的主要過程就是先分詞后過濾。

    ?

    l?分詞:采集到的數(shù)據(jù)會(huì)存儲(chǔ)到document對(duì)象的Field域中,分詞就是將DocumentFieldvalue值切分成一個(gè)一個(gè)的詞。

    l?過濾:包括去除標(biāo)點(diǎn)符號(hào)過濾、去除停用詞過濾(的、是、aanthe等)、大寫轉(zhuǎn)小寫、詞的形還原(復(fù)數(shù)形式轉(zhuǎn)成單數(shù)形參、過去式轉(zhuǎn)成現(xiàn)在式。。。)等。?

    ?

    什么是停用詞?停用詞是為節(jié)省存儲(chǔ)空間和提高搜索效率,搜索引擎在索引頁面或處理搜索請(qǐng)求時(shí)會(huì)自動(dòng)忽略某些字或詞,這些字或詞即被稱為Stop Words(停用詞)。比如語氣助詞、副詞、介詞、連接詞等,通常自身并無明確的意義,只有將其放入一個(gè)完整的句子中才有一定作用,如常見的“的”、“在”、“是”、“啊”等。

    ?

    對(duì)于分詞來說,不同的語言,分詞規(guī)則不同。Lucene作為一個(gè)工具包提供不同國家的分詞器,本例子使用StandardAnalyzer,它可以對(duì)用英文進(jìn)行分詞

    ?

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

    ??@Override

    ??protected?TokenStreamComponents createComponents(final?String fieldName, final?Reader?reader) {

    ????final?StandardTokenizer?src?= new?StandardTokenizer(getVersion(), reader);

    ????src.setMaxTokenLength(maxTokenLength);

    ????TokenStream tok?= new?StandardFilter(getVersion(), src);

    ????tok?= new?LowerCaseFilter(getVersion(), tok);

    ????tok?= new?StopFilter(getVersion(), tok, stopwords);

    ????return?new?TokenStreamComponents(src, tok) {

    ??????@Override

    ??????protected?void?setReader(final?Reader reader) throws?IOException {

    ????????src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);

    ????????super.setReader(reader);

    ??????}

    ????};

    ??}

    ?

    Tokenizer就是分詞器,負(fù)責(zé)將reader轉(zhuǎn)換為語匯單元即進(jìn)行分詞處理,Lucene提供了很多的分詞器,也可以使用第三方的分詞,比如IKAnalyzer一個(gè)中文分詞器。

    ?

    TokenFilter是分詞過濾器,負(fù)責(zé)對(duì)語匯單元進(jìn)行過濾,TokenFilter可以是一個(gè)過濾器鏈兒,Lucene提供了很多的分詞器過濾器,比如大小寫轉(zhuǎn)換、去除停用詞等。

    ?

    如下圖是語匯單元的生成過程:

    ?

    ?

    ?

    從一個(gè)Reader字符流開始,創(chuàng)建一個(gè)基于ReaderTokenizer分詞器,經(jīng)過三個(gè)TokenFilter生成語匯單元Token

    ?

    比如下邊的文檔經(jīng)過分析器分析如下:

    • 原文檔內(nèi)容:

    ?

    ?

    ?

    ?

    • 分析后得到的多個(gè)語匯單元:

    ?

    ?

    ?

    ?

    ?

    6.2.?Analyzer使用時(shí)機(jī)

    6.2.1.?索引時(shí)使用Analyzer

    輸入關(guān)鍵字進(jìn)行搜索,當(dāng)需要讓該關(guān)鍵字與文檔域內(nèi)容所包含的詞進(jìn)行匹配時(shí)需要對(duì)文檔域內(nèi)容進(jìn)行分析,需要經(jīng)過Analyzer分析器處理生成語匯單元(Token)。分析器分析的對(duì)象是文檔中的Field域。當(dāng)Field的屬性tokenized(是否分詞)為true時(shí)會(huì)對(duì)Field值進(jìn)行分析,如下圖:

    ?

    ?

    ?

    對(duì)于一些Field可以不用分析

    1、不作為查詢條件的內(nèi)容,比如文件路徑

    2、不是匹配內(nèi)容中的詞而匹配Field的整體內(nèi)容,比如訂單號(hào)、身份證號(hào)等。

    ?

    ?

    6.2.2.?搜索時(shí)使用Analyzer

    對(duì)搜索關(guān)鍵字進(jìn)行分析和索引分析一樣,使用Analyzer對(duì)搜索關(guān)鍵字進(jìn)行分析、分詞處理,使用分析后每個(gè)詞語進(jìn)行搜索。比如:搜索關(guān)鍵字:spring web ,經(jīng)過分析器進(jìn)行分詞,得出:spring??web拿詞去索引詞典表查找 ,找到索引鏈接到Document,解析Document內(nèi)容。

    對(duì)于匹配整體Field域的查詢可以在搜索時(shí)不分析,比如根據(jù)訂單號(hào)、身份證號(hào)查詢等。

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

    ?

    6.3.?中文分詞器

    6.3.1.?什么是中文分詞器

    學(xué)過英文的都知道,英文是以單詞為單位的,單詞與單詞之間以空格或者逗號(hào)句號(hào)隔開。所以對(duì)于英文,我們可以簡單以空格判斷某個(gè)字符串是否為一個(gè)單詞,比如I love Chinalove China很容易被程序區(qū)分開來。

    ?

    而中文則以字為單位,字又組成詞,字和詞再組成句子。中文“我愛中國”就不一樣了,電腦不知道“中國”是一個(gè)詞語還是“愛中”是一個(gè)詞語。

    ?

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

    ?

    6.3.2.?Lucene自帶中文分詞器

    l?StandardAnalyzer:

    單字分詞:就是按照中文一個(gè)字一個(gè)字地進(jìn)行分詞。如:“我愛中國”
    效果:愛”

    ?

    l?CJKAnalyzer

    二分法分詞:按兩個(gè)字進(jìn)行切分。如:中國人,效果:是”中國“國人”

    ?

    上邊兩個(gè)分詞器無法滿足需求。

    l?SmartChineseAnalyzer

    對(duì)中文支持較好,但擴(kuò)展性差,擴(kuò)展詞庫,禁用詞庫和同義詞庫等不好處理

    ?

    6.4.?第三方中文分詞器

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

    ?

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

    ?

    l?IK-analyzer 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10從2006年12月推出1.0版開始, IKAnalyzer已經(jīng)推出了4個(gè)大版本。最初,它是以開源項(xiàng)目Luence為應(yīng)用主體的,結(jié)合詞典分詞和文法分析算法的中文分詞組件。從3.0版本開 始,IK發(fā)展為面向Java的公用分詞組件,獨(dú)立于Lucene項(xiàng)目,同時(shí)提供了對(duì)Lucene的默認(rèn)優(yōu)化實(shí)現(xiàn)。在2012版本中,IK實(shí)現(xiàn)了簡單的分詞 歧義排除算法,標(biāo)志著IK分詞器從單純的詞典分詞向模擬語義分詞衍化。 但是也就是2012年12月后沒有在更新。

    ?

    l?ansj_seg:最新版本在?https://github.com/NLPchina/ansj_seg?tags僅有1.1版本,從2012年到2014年更新了大小6次,但是作者本人在2014年10月10日說明:“可能我以后沒有精力來維護(hù)ansj_seg了”,現(xiàn)在由”nlp_china”管理。2014年11月有更新。并未說明是否支持Lucene,是一個(gè)由CRF(條件隨機(jī)場)算法所做的分詞算法。

    ?

    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.?修改分詞器代碼

    @Test

    public?void?testCreateIndex() throws?Exception {

    // 1. 采集數(shù)據(jù)

    BookDao bookDao?= new?BookDaoImpl();

    List<Book> bookList?= bookDao.queryBookList();

    ?

    // 2. 創(chuàng)建Document文檔對(duì)象

    List<Document> documents?= new?ArrayList<>();

    for?(Book book?: bookList) {

    Document document?= new?Document();

    ?

    // Document文檔中添加Field域

    // 圖書Id

    // Store.YES:表示存儲(chǔ)到文檔域中

    document.add(new?TextField("id", book.getId().toString(), Store.YES));

    // 圖書名稱

    document.add(new?TextField("name", book.getName().toString(), Store.YES));

    // 圖書價(jià)格

    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. 創(chuàng)建Analyzer分詞器,分析文檔,對(duì)文檔進(jìn)行分詞

    // Analyzer analyzer = new StandardAnalyzer();

    Analyzer analyzer?= new?IKAnalyzer();

    ?

    // 4. 創(chuàng)建Directory對(duì)象,聲明索引庫的位置

    Directory directory?= FSDirectory.open(new?File("C:/itcast/lucene/index"));

    ?

    // 5. 創(chuàng)建IndexWriteConfig對(duì)象,寫入索引需要的配置

    IndexWriterConfig config?= new?IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);

    ?

    // 6.創(chuàng)建IndexWriter寫入對(duì)象

    IndexWriter indexWriter?= new?IndexWriter(directory, config);

    ?

    // 7.寫入到索引庫,通過IndexWriter添加文檔對(duì)象document

    for?(Document doc?: documents) {

    indexWriter.addDocument(doc);

    }

    ?

    // 8.釋放資源

    indexWriter.close();

    }

    ?

    6.6.?擴(kuò)展中文詞庫

    如果想配置擴(kuò)展詞和停用詞,就創(chuàng)建擴(kuò)展詞的文件和停用詞的文件。

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

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ikanalyzer包中拷貝配置文件

    ?

    ?

    ?

    拷貝資源文件夾中

    ?

    ?

    ?

    IKAnalyzer.cfg.xml配置文件

    <?xml?version="1.0"?encoding="UTF-8"?>

    <!DOCTYPE?properties?SYSTEM?"http://java.sun.com/dtd/properties.dtd">??

    <properties>??

    <comment>IK Analyzer 擴(kuò)展配置</comment>

    <!--用戶可以在這里配置自己的擴(kuò)展字典 -->

    <entry?key="ext_dict">ext.dic;</entry>?

    ?

    <!--用戶可以在這里配置自己的擴(kuò)展停止詞字典-->

    <entry?key="ext_stopwords">stopword.dic;</entry>?

    ?

    </properties>

    ?

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

    ?

    ?

    ?

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

    ?

    ?

    ?

    最終分詞效果

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/shan1393/p/9343630.html

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的lucene 第一天的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。