搜索學(xué)習(xí)入門--Lucene初體驗(yàn)(Lucene索引的增刪改查)

Lucene是一個(gè)開(kāi)放源代碼的全文檢索引擎工具包,它提供了完整的查詢引擎和索引引擎,開(kāi)發(fā)人員可以方便的在目標(biāo)系統(tǒng)中實(shí)現(xiàn)全文檢索探熔。Lucene的核心使用的是基于倒排索引的,并且實(shí)現(xiàn)了實(shí)現(xiàn)了分塊索引烘挫。下面诀艰,先來(lái)體驗(yàn)一下Lucene對(duì)索引的增刪改查功能。Lucene存儲(chǔ)對(duì)象是以document為存儲(chǔ)單元饮六,對(duì)象中相關(guān)的屬性值則存放到Field中其垄。

第一步:引入依賴

<!-- Lucene核心 -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>4.7.2</version>
</dependency>

<!-- Lucene搜索查詢相關(guān) -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-queryparser</artifactId>
    <version>4.7.2</version>
</dependency>

<!-- Lucene分詞器相關(guān) -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-analyzers-common</artifactId>
    <version>4.7.2</version>
</dependency>

第二步:建立索引

這里使用標(biāo)準(zhǔn)分詞器建立5個(gè)Document的索引

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.IOException;

/**
 * created by yuyufeng on 2017/11/13.
 */
public class LuceneIndexDemo {
    public static void main(String[] args) {
        // Lucene Document的域名
        String fieldName = "blog";
        String text = "";
        // 建立5條索引
        text = "10月11日杭州云棲大會(huì)上,馬云表達(dá)了對(duì)新建成的阿里巴巴全球研究院—阿里巴巴達(dá)摩院的愿景卤橄,希望達(dá)摩院二十年內(nèi)成為世界第一大經(jīng)濟(jì)體绿满,服務(wù)世界二十億人,創(chuàng)造一億個(gè)工作崗位虽风。";
        doIndex(fieldName, text);
        text = "中國(guó)互聯(lián)網(wǎng)界棒口,阿里巴巴被認(rèn)為是技術(shù)實(shí)力最弱的公司。我確實(shí)不懂技術(shù)辜膝,承認(rèn)不懂技術(shù)不丟人无牵,不懂裝懂才丟人。";
        doIndex(fieldName, text);
        text = "阿里巴巴未來(lái)二十年的目標(biāo)是打造世界第五大經(jīng)濟(jì)體厂抖,不是我們狂妄茎毁,而是世界需要這么一個(gè)經(jīng)濟(jì)體,也一定會(huì)有這么一個(gè)經(jīng)濟(jì)體忱辅。";
        doIndex(fieldName, text);
        text = "達(dá)摩院一定也必須要超越英特爾七蜘,必須超越微軟,必須超越IBM墙懂,因?yàn)槲覀兩诙皇兰o(jì)橡卤,我們是有機(jī)會(huì)后發(fā)優(yōu)勢(shì)的。";
        doIndex(fieldName, text);
        text = "阿里巴巴有很多爭(zhēng)議损搬,似乎無(wú)處不在碧库,我還真想不出有什么東西是我們不做的柜与。互聯(lián)網(wǎng)是一種思想嵌灰,是一種技術(shù)革命弄匕,不應(yīng)該有界限」敛t?缃鐦?lè)趣無(wú)窮迁匠。我覺(jué)得阿里巴巴的跨界還不錯(cuò)";
        doIndex(fieldName, text);


    }

    private static void doIndex(String fieldName, String text) {
        // 實(shí)例化IKAnalyzer分詞器
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_47);

        Directory directory = null;
        IndexWriter iwriter;
        try {
            // 索引目錄
            directory = new SimpleFSDirectory(new File("D://test/lucene_index"));

            // 配置IndexWriterConfig
            IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_47, analyzer);
            iwConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
            iwriter = new IndexWriter(directory, iwConfig);
            // 寫入索引
            Document doc = new Document();
            Long id = System.currentTimeMillis();
            doc.add(new StringField("ID", id+"", Field.Store.YES));
            doc.add(new TextField(fieldName, text, Field.Store.YES));
            iwriter.addDocument(doc);
            iwriter.close();
            System.out.println("建立索引成功:" + id);
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (directory != null) {
                try {
                    directory.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

運(yùn)行結(jié)果
建立索引成功:1510579712099
建立索引成功:1510579712355
建立索引成功:1510579712512
建立索引成功:1510579712743
建立索引成功:1510579712912

查看索引文件:運(yùn)行之后,打開(kāi)我們存放索引的文件夾驹溃,你會(huì)看到如下文件列表結(jié)構(gòu):

這里寫圖片描述

第三步:搜索查詢

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriterConfig;
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.SimpleFSDirectory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.IOException;

/**
 * created by yuyufeng on 2017/11/13.
 */
public class LuceneSearchDemo {
    public static void main(String[] args) {

        // Lucene Document的域名
        String fieldName = "blog";
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_47);
        Directory directory = null;
        IndexReader ireader = null;
        IndexSearcher isearcher;

        try {
            //索引目錄
            directory = new SimpleFSDirectory(new File("D://test/lucene_index"));
            // 配置IndexWriterConfig
            IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_47, analyzer);
            iwConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

            // 搜索過(guò)程**********************************
            // 實(shí)例化搜索器
            ireader = DirectoryReader.open(directory);
            isearcher = new IndexSearcher(ireader);

            String keyword = "達(dá)摩院";
            // 使用QueryParser查詢分析器構(gòu)造Query對(duì)象
            QueryParser qp = new QueryParser(Version.LUCENE_47, fieldName, analyzer);
            qp.setDefaultOperator(QueryParser.OR_OPERATOR);  // and or 跟數(shù)據(jù)庫(kù)查詢語(yǔ)法類似
            Query query = qp.parse(keyword);
            System.out.println("Query = " + query);

            // 搜索相似度最高的5條記錄
            TopDocs topDocs = isearcher.search(query, 5);
            System.out.println("命中:" + topDocs.totalHits);
            // 遍歷輸出結(jié)果
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (int i = 0; i < topDocs.totalHits; i++) {
                Document targetDoc = isearcher.doc(scoreDocs[i].doc);
                System.out.println("內(nèi)容:" + targetDoc.toString());
            }
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ireader != null) {
                try {
                    ireader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (directory != null) {
                try {
                    directory.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

**keyword= :"達(dá)摩院"
運(yùn)行結(jié)果

Query = blog:達(dá) blog:摩 blog:院
命中:2
內(nèi)容:Document<<stored<ID:1510579934220> stored,indexed,tokenized<blog:10月11日杭州云棲大會(huì)上城丧,馬云表達(dá)了對(duì)新建成的阿里巴巴全球研究院—阿里巴巴達(dá)摩院的愿景,希望達(dá)摩院二十年內(nèi)成為世界第一大經(jīng)濟(jì)體吠架,服務(wù)世界二十億人芙贫,創(chuàng)造一億個(gè)工作崗位搂鲫。>>
內(nèi)容:Document<stored<ID:1510579934765> stored,indexed,tokenized<blog:達(dá)摩院一定也必須要超越英特爾傍药,必須超越微軟,必須超越IBM魂仍,因?yàn)槲覀兩诙皇兰o(jì)拐辽,我們是有機(jī)會(huì)后發(fā)優(yōu)勢(shì)的。>>    

**keyword= :"阿里巴巴達(dá)摩院"
運(yùn)行結(jié)果

Query = blog:阿 blog:里 blog:巴 blog:巴 blog:達(dá) blog:摩 blog:院
命中:5
內(nèi)容:Document<stored<ID:1510579934220> stored,indexed,tokenized<blog:10月11日杭州云棲大會(huì)上擦酌,馬云表達(dá)了對(duì)新建成的阿里巴巴全球研究院—阿里巴巴達(dá)摩院的愿景俱诸,希望達(dá)摩院二十年內(nèi)成為世界第一大經(jīng)濟(jì)體,服務(wù)世界二十億人赊舶,創(chuàng)造一億個(gè)工作崗位睁搭。>>
內(nèi)容:Document<stored<ID:1510579934932> stored,indexed,tokenized<blog:阿里巴巴有很多爭(zhēng)議,似乎無(wú)處不在笼平,我還真想不出有什么東西是我們不做的园骆。互聯(lián)網(wǎng)是一種思想寓调,是一種技術(shù)革命锌唾,不應(yīng)該有界限《嵊ⅲ跨界樂(lè)趣無(wú)窮晌涕。我覺(jué)得阿里巴巴的跨界還不錯(cuò)>>
內(nèi)容:Document<stored<ID:1510579934765> stored,indexed,tokenized<blog:達(dá)摩院一定也必須要超越英特爾,必須超越微軟痛悯,必須超越IBM余黎,因?yàn)槲覀兩诙皇兰o(jì),我們是有機(jī)會(huì)后發(fā)優(yōu)勢(shì)的载萌。>>
內(nèi)容:Document<stored<ID:1510579934474> stored,indexed,tokenized<blog:中國(guó)互聯(lián)網(wǎng)界惧财,阿里巴巴被認(rèn)為是技術(shù)實(shí)力最弱的公司亲族。我確實(shí)不懂技術(shù),承認(rèn)不懂技術(shù)不丟人可缚,不懂裝懂才丟人霎迫。>>
內(nèi)容:Document<stored<ID:1510579934606> stored,indexed,tokenized<blog:阿里巴巴未來(lái)二十年的目標(biāo)是打造世界第五大經(jīng)濟(jì)體,不是我們狂妄帘靡,而是世界需要這么一個(gè)經(jīng)濟(jì)體知给,也一定會(huì)有這么一個(gè)經(jīng)濟(jì)體。>>

第四步:更新索引文檔

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;

public class LuceneUpdateDemo {
    public static void main(String[] args) {
        // 實(shí)例化IKAnalyzer分詞器
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_47);

        Directory directory = null;
        IndexWriter iwriter;
        try {
            // 索引目錄
            directory = new SimpleFSDirectory(new File("D://test/lucene_index"));

            // 配置IndexWriterConfig
            IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_47, analyzer);
            iwConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
            iwriter = new IndexWriter(directory, iwConfig);
            // 寫入索引
            Document doc = new Document();
            String id = "1510579934220";
            doc.add(new StringField("ID", id, Field.Store.YES));
            doc.add(new TextField("blog", "更新文檔后->達(dá)摩院一定也必須要超越英特爾描姚,必須超越微軟涩赢,必須超越IBM,因?yàn)槲覀兩诙皇兰o(jì)轩勘,我們是有機(jī)會(huì)后發(fā)優(yōu)勢(shì)的筒扒。", Field.Store.YES));
            //先根據(jù)Term ID 刪除,在建立新的索引
            iwriter.updateDocument(new Term("ID", id), doc);
            iwriter.close();
            System.out.println("更新索引成功:" + 1511233039462L);
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (directory != null) {
                try {
                    directory.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在執(zhí)行第三步查詢绊寻,即可查看更新結(jié)果

第五步:索引刪除

package top.yuyufeng.learn.lucene.demo1;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.*;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.IOException;

/**
 * @author yuyufeng
 * @date 2017/11/21
 */
public class LuceneDeleteDemo {
    public static void main(String[] args) {
        // Lucene Document的域名
        String fieldName = "blog";
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_47);
        Directory directory = null;
        IndexReader ireader = null;
        IndexSearcher isearcher;
        IndexWriter iwriter = null;
        try {
            //索引目錄
            directory = new SimpleFSDirectory(new File("D://test/lucene_index"));
            // 配置IndexWriterConfig
            IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_47, analyzer);
            iwConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
            ireader = DirectoryReader.open(directory);
            iwriter = new IndexWriter(directory, iwConfig);
            iwriter.deleteDocuments(new Term("ID","1511235710648"));
            //使用IndexWriter進(jìn)行Document刪除操作時(shí)花墩,文檔并不會(huì)立即被刪除,而是把這個(gè)刪除動(dòng)作緩存起來(lái)澄步,當(dāng)IndexWriter.Commit()或IndexWriter.Close()時(shí)冰蘑,刪除操作才會(huì)被真正執(zhí)行。
            iwriter.commit();
            iwriter.close();
            ireader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (directory != null) {
                try {
                    directory.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
方法 說(shuō)明
DeleteDocuments(Query query) 根據(jù)Query條件來(lái)刪除單個(gè)或多個(gè)Document
DeleteDocuments(Query[] queries) 根據(jù)Query條件來(lái)刪除單個(gè)或多個(gè)Document
DeleteDocuments(Term term) 根據(jù)Term來(lái)刪除單個(gè)或多個(gè)Document
DeleteDocuments(Term[] terms) 根據(jù)Term來(lái)刪除單個(gè)或多個(gè)Document
DeleteAll() 刪除所有的Document
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末村缸,一起剝皮案震驚了整個(gè)濱河市祠肥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梯皿,老刑警劉巖仇箱,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異东羹,居然都是意外死亡剂桥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門百姓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)渊额,“玉大人,你說(shuō)我怎么就攤上這事垒拢⊙#” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵求类,是天一觀的道長(zhǎng)奔垦。 經(jīng)常有香客問(wèn)我,道長(zhǎng)尸疆,這世上最難降的妖魔是什么椿猎? 我笑而不...
    開(kāi)封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任惶岭,我火速辦了婚禮,結(jié)果婚禮上犯眠,老公的妹妹穿的比我還像新娘按灶。我一直安慰自己,他們只是感情好筐咧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布鸯旁。 她就那樣靜靜地躺著,像睡著了一般量蕊。 火紅的嫁衣襯著肌膚如雪铺罢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天残炮,我揣著相機(jī)與錄音韭赘,去河邊找鬼。 笑死势就,一個(gè)胖子當(dāng)著我的面吹牛泉瞻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛋勺,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼瓦灶,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鸠删!你這毒婦竟也來(lái)了抱完?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刃泡,失蹤者是張志新(化名)和其女友劉穎巧娱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烘贴,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡禁添,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了桨踪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片老翘。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锻离,靈堂內(nèi)的尸體忽然破棺而出铺峭,到底是詐尸還是另有隱情,我是刑警寧澤汽纠,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布卫键,位于F島的核電站,受9級(jí)特大地震影響虱朵,放射性物質(zhì)發(fā)生泄漏莉炉。R本人自食惡果不足惜钓账,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望絮宁。 院中可真熱鬧梆暮,春花似錦、人聲如沸绍昂。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)治专。三九已至卖陵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間张峰,已是汗流浹背泪蔫。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喘批,地道東北人撩荣。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像饶深,于是被迫代替她去往敵國(guó)和親餐曹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容