詳解Spring Boot 中使用 Java API 調(diào)用 lucene
Lucene是apache軟件基金會(huì)4 jakarta項(xiàng)目組的一個(gè)子項(xiàng)目,是一個(gè)開(kāi)放源代碼的全文檢索引擎工具包,但它不是一個(gè)完整的全文檢索引擎,而是一個(gè)全文檢索引擎的架構(gòu),提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語(yǔ)言)。Lucene的目的是為軟件開(kāi)發(fā)人員提供一個(gè)簡(jiǎn)單易用的工具包,以方便的在目標(biāo)系統(tǒng)中實(shí)現(xiàn)全文檢索的功能,或者是以此為基礎(chǔ)建立起完整的全文檢索引擎
全文檢索概述
比如,我們一個(gè)文件夾中,或者一個(gè)磁盤(pán)中有很多的文件,記事本、world、Excel、pdf,我們想根據(jù)其中的關(guān)鍵詞搜索包含的文件。例如,我們輸入Lucene,所有內(nèi)容含有Lucene的文件就會(huì)被檢查出來(lái)。這就是所謂的全文檢索。
因此,很容易的我們想到,應(yīng)該建立一個(gè)關(guān)鍵字與文件的相關(guān)映射,盜用ppt中的一張圖,很明白的解釋了這種映射如何實(shí)現(xiàn)。
倒排索引

有了這種映射關(guān)系,我們就來(lái)看看Lucene的架構(gòu)設(shè)計(jì)。
下面是Lucene的資料必出現(xiàn)的一張圖,但也是其精髓的概括。

我們可以看到,Lucene的使用主要體現(xiàn)在兩個(gè)步驟:
1 創(chuàng)建索引,通過(guò)IndexWriter對(duì)不同的文件進(jìn)行索引的創(chuàng)建,并將其保存在索引相關(guān)文件存儲(chǔ)的位置中。
2 通過(guò)索引查尋關(guān)鍵字相關(guān)文檔。
在Lucene中,就是使用這種“倒排索引”的技術(shù),來(lái)實(shí)現(xiàn)相關(guān)映射。
Lucene數(shù)學(xué)模型
文檔、域、詞元
文檔是Lucene搜索和索引的原子單位,文檔為包含一個(gè)或者多個(gè)域的容器,而域則是依次包含“真正的”被搜索的內(nèi)容,域值通過(guò)分詞技術(shù)處理,得到多個(gè)詞元。
For Example,一篇小說(shuō)(斗破蒼穹)信息可以稱為一個(gè)文檔,小說(shuō)信息又包含多個(gè)域,例如:標(biāo)題(斗破蒼穹)、作者、簡(jiǎn)介、最后更新時(shí)間等等,對(duì)標(biāo)題這個(gè)域采用分詞技術(shù)又可以得到一個(gè)或者多個(gè)詞元(斗、破、蒼、穹)。
Lucene文件結(jié)構(gòu)
層次結(jié)構(gòu)
index
一個(gè)索引存放在一個(gè)目錄中
segment
一個(gè)索引中可以有多個(gè)段,段與段之間是獨(dú)立的,添加新的文檔可能產(chǎn)生新段,不同的段可以合并成一個(gè)新段
document
文檔是創(chuàng)建索引的基本單位,不同的文檔保存在不同的段中,一個(gè)段可以包含多個(gè)文檔
field
域,一個(gè)文檔包含不同類(lèi)型的信息,可以拆分開(kāi)索引
term
詞,索引的最小單位,是經(jīng)過(guò)詞法分析和語(yǔ)言處理后的數(shù)據(jù)。
正向信息
按照層次依次保存了從索引到詞的包含關(guān)系:index-->segment-->document-->field-->term。
反向信息
反向信息保存了詞典的倒排表映射:term-->document
IndexWriter
lucene中最重要的的類(lèi)之一,它主要是用來(lái)將文檔加入索引,同時(shí)控制索引過(guò)程中的一些參數(shù)使用。
Analyzer
分析器,主要用于分析搜索引擎遇到的各種文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。
Directory
索引存放的位置;lucene提供了兩種索引存放的位置,一種是磁盤(pán),一種是內(nèi)存。一般情況將索引放在磁盤(pán)上;相應(yīng)地lucene提供了FSDirectory和RAMDirectory兩個(gè)類(lèi)。
Document
文檔;Document相當(dāng)于一個(gè)要進(jìn)行索引的單元,任何可以想要被索引的文件都必須轉(zhuǎn)化為Document對(duì)象才能進(jìn)行索引。
Field
字段。
IndexSearcher
是lucene中最基本的檢索工具,所有的檢索都會(huì)用到IndexSearcher工具;
Query
查詢,lucene中支持模糊查詢,語(yǔ)義查詢,短語(yǔ)查詢,組合查詢等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些類(lèi)。
QueryParser
是一個(gè)解析用戶輸入的工具,可以通過(guò)掃描用戶輸入的字符串,生成Query對(duì)象。
Hits
在搜索完成之后,需要把搜索結(jié)果返回并顯示給用戶,只有這樣才算是完成搜索的目的。在lucene中,搜索的結(jié)果的集合是用Hits類(lèi)的實(shí)例來(lái)表示的。
測(cè)試用例
Github 代碼
代碼我已放到 Github ,導(dǎo)入spring-boot-lucene-demo 項(xiàng)目
github spring-boot-lucene-demo
添加依賴
<!--對(duì)分詞索引查詢解析-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>7.1.0</version>
</dependency>
<!--高亮 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>7.1.0</version>
</dependency>
<!--smartcn 中文分詞器 SmartChineseAnalyzer smartcn分詞器 需要lucene依賴 且和lucene版本同步-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>7.1.0</version>
</dependency>
<!--ik-analyzer 中文分詞器-->
<dependency>
<groupId>cn.bestwu</groupId>
<artifactId>ik-analyzers</artifactId>
<version>5.1.0</version>
</dependency>
<!--MMSeg4j 分詞器-->
<dependency>
<groupId>com.chenlb.mmseg4j</groupId>
<artifactId>mmseg4j-solr</artifactId>
<version>2.4.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
</exclusion>
</exclusions>
</dependency>
配置 lucene
private Directory directory;
private IndexReader indexReader;
private IndexSearcher indexSearcher;
@Before
public void setUp() throws IOException {
//索引存放的位置,設(shè)置在當(dāng)前目錄中
directory = FSDirectory.open(Paths.get("indexDir/"));
//創(chuàng)建索引的讀取器
indexReader = DirectoryReader.open(directory);
//創(chuàng)建一個(gè)索引的查找器,來(lái)檢索索引庫(kù)
indexSearcher = new IndexSearcher(indexReader);
}
@After
public void tearDown() throws Exception {
indexReader.close();
}
**
* 執(zhí)行查詢,并打印查詢到的記錄數(shù)
*
* @param query
* @throws IOException
*/
public void executeQuery(Query query) throws IOException {
TopDocs topDocs = indexSearcher.search(query, 100);
//打印查詢到的記錄數(shù)
System.out.println("總共查詢到" + topDocs.totalHits + "個(gè)文檔");
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
//取得對(duì)應(yīng)的文檔對(duì)象
Document document = indexSearcher.doc(scoreDoc.doc);
System.out.println("id:" + document.get("id"));
System.out.println("title:" + document.get("title"));
System.out.println("content:" + document.get("content"));
}
}
/**
* 分詞打印
*
* @param analyzer
* @param text
* @throws IOException
*/
public void printAnalyzerDoc(Analyzer analyzer, String text) throws IOException {
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
try {
tokenStream.reset();
while (tokenStream.incrementToken()) {
System.out.println(charTermAttribute.toString());
}
tokenStream.end();
} finally {
tokenStream.close();
analyzer.close();
}
}
創(chuàng)建索引
@Test
public void indexWriterTest() throws IOException {
long start = System.currentTimeMillis();
//索引存放的位置,設(shè)置在當(dāng)前目錄中
Directory directory = FSDirectory.open(Paths.get("indexDir/"));
//在 6.6 以上版本中 version 不再是必要的,并且,存在無(wú)參構(gòu)造方法,可以直接使用默認(rèn)的 StandardAnalyzer 分詞器。
Version version = Version.LUCENE_7_1_0;
//Analyzer analyzer = new StandardAnalyzer(); // 標(biāo)準(zhǔn)分詞器,適用于英文
//Analyzer analyzer = new SmartChineseAnalyzer();//中文分詞
//Analyzer analyzer = new ComplexAnalyzer();//中文分詞
//Analyzer analyzer = new IKAnalyzer();//中文分詞
Analyzer analyzer = new IKAnalyzer();//中文分詞
//創(chuàng)建索引寫(xiě)入配置
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
//創(chuàng)建索引寫(xiě)入對(duì)象
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
//創(chuàng)建Document對(duì)象,存儲(chǔ)索引
Document doc = new Document();
int id = 1;
//將字段加入到doc中
doc.add(new IntPoint("id", id));
doc.add(new StringField("title", "Spark", Field.Store.YES));
doc.add(new TextField("content", "Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎", Field.Store.YES));
doc.add(new StoredField("id", id));
//將doc對(duì)象保存到索引庫(kù)中
indexWriter.addDocument(doc);
indexWriter.commit();
//關(guān)閉流
indexWriter.close();
long end = System.currentTimeMillis();
System.out.println("索引花費(fèi)了" + (end - start) + " 毫秒");
}
響應(yīng)
17:58:14.655 [main] DEBUG org.wltea.analyzer.dic.Dictionary - 加載擴(kuò)展詞典:ext.dic 17:58:14.660 [main] DEBUG org.wltea.analyzer.dic.Dictionary - 加載擴(kuò)展停止詞典:stopword.dic 索引花費(fèi)了879 毫秒
刪除文檔
@Test
public void deleteDocumentsTest() throws IOException {
//Analyzer analyzer = new StandardAnalyzer(); // 標(biāo)準(zhǔn)分詞器,適用于英文
//Analyzer analyzer = new SmartChineseAnalyzer();//中文分詞
//Analyzer analyzer = new ComplexAnalyzer();//中文分詞
//Analyzer analyzer = new IKAnalyzer();//中文分詞
Analyzer analyzer = new IKAnalyzer();//中文分詞
//創(chuàng)建索引寫(xiě)入配置
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
//創(chuàng)建索引寫(xiě)入對(duì)象
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
// 刪除title中含有關(guān)鍵詞“Spark”的文檔
long count = indexWriter.deleteDocuments(new Term("title", "Spark"));
// 除此之外IndexWriter還提供了以下方法:
// 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
//使用IndexWriter進(jìn)行Document刪除操作時(shí),文檔并不會(huì)立即被刪除,而是把這個(gè)刪除動(dòng)作緩存起來(lái),當(dāng)IndexWriter.Commit()或IndexWriter.Close()時(shí),刪除操作才會(huì)被真正執(zhí)行。
indexWriter.commit();
indexWriter.close();
System.out.println("刪除完成:" + count);
}
響應(yīng)
刪除完成:1
更新文檔
/**
* 測(cè)試更新
* 實(shí)際上就是刪除后新增一條
*
* @throws IOException
*/
@Test
public void updateDocumentTest() throws IOException {
//Analyzer analyzer = new StandardAnalyzer(); // 標(biāo)準(zhǔn)分詞器,適用于英文
//Analyzer analyzer = new SmartChineseAnalyzer();//中文分詞
//Analyzer analyzer = new ComplexAnalyzer();//中文分詞
//Analyzer analyzer = new IKAnalyzer();//中文分詞
Analyzer analyzer = new IKAnalyzer();//中文分詞
//創(chuàng)建索引寫(xiě)入配置
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
//創(chuàng)建索引寫(xiě)入對(duì)象
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
Document doc = new Document();
int id = 1;
doc.add(new IntPoint("id", id));
doc.add(new StringField("title", "Spark", Field.Store.YES));
doc.add(new TextField("content", "Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎", Field.Store.YES));
doc.add(new StoredField("id", id));
long count = indexWriter.updateDocument(new Term("id", "1"), doc);
System.out.println("更新文檔:" + count);
indexWriter.close();
}
響應(yīng)
更新文檔:1
按詞條搜索
/**
* 按詞條搜索
* <p>
* TermQuery是最簡(jiǎn)單、也是最常用的Query。TermQuery可以理解成為“詞條搜索”,
* 在搜索引擎中最基本的搜索就是在索引中搜索某一詞條,而TermQuery就是用來(lái)完成這項(xiàng)工作的。
* 在Lucene中詞條是最基本的搜索單位,從本質(zhì)上來(lái)講一個(gè)詞條其實(shí)就是一個(gè)名/值對(duì)。
* 只不過(guò)這個(gè)“名”是字段名,而“值”則表示字段中所包含的某個(gè)關(guān)鍵字。
*
* @throws IOException
*/
@Test
public void termQueryTest() throws IOException {
String searchField = "title";
//這是一個(gè)條件查詢的api,用于添加條件
TermQuery query = new TermQuery(new Term(searchField, "Spark"));
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(query);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
多條件查詢
/**
* 多條件查詢
*
* BooleanQuery也是實(shí)際開(kāi)發(fā)過(guò)程中經(jīng)常使用的一種Query。
* 它其實(shí)是一個(gè)組合的Query,在使用時(shí)可以把各種Query對(duì)象添加進(jìn)去并標(biāo)明它們之間的邏輯關(guān)系。
* BooleanQuery本身來(lái)講是一個(gè)布爾子句的容器,它提供了專(zhuān)門(mén)的API方法往其中添加子句,
* 并標(biāo)明它們之間的關(guān)系,以下代碼為BooleanQuery提供的用于添加子句的API接口:
*
* @throws IOException
*/
@Test
public void BooleanQueryTest() throws IOException {
String searchField1 = "title";
String searchField2 = "content";
Query query1 = new TermQuery(new Term(searchField1, "Spark"));
Query query2 = new TermQuery(new Term(searchField2, "Apache"));
BooleanQuery.Builder builder = new BooleanQuery.Builder();
// BooleanClause用于表示布爾查詢子句關(guān)系的類(lèi),
// 包 括:
// BooleanClause.Occur.MUST,
// BooleanClause.Occur.MUST_NOT,
// BooleanClause.Occur.SHOULD。
// 必須包含,不能包含,可以包含三種.有以下6種組合:
//
// 1.MUST和MUST:取得連個(gè)查詢子句的交集。
// 2.MUST和MUST_NOT:表示查詢結(jié)果中不能包含MUST_NOT所對(duì)應(yīng)得查詢子句的檢索結(jié)果。
// 3.SHOULD與MUST_NOT:連用時(shí),功能同MUST和MUST_NOT。
// 4.SHOULD與MUST連用時(shí),結(jié)果為MUST子句的檢索結(jié)果,但是SHOULD可影響排序。
// 5.SHOULD與SHOULD:表示“或”關(guān)系,最終檢索結(jié)果為所有檢索子句的并集。
// 6.MUST_NOT和MUST_NOT:無(wú)意義,檢索無(wú)結(jié)果。
builder.add(query1, BooleanClause.Occur.SHOULD);
builder.add(query2, BooleanClause.Occur.SHOULD);
BooleanQuery query = builder.build();
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(query);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
匹配前綴
/**
* 匹配前綴
* <p>
* PrefixQuery用于匹配其索引開(kāi)始以指定的字符串的文檔。就是文檔中存在xxx%
* <p>
*
* @throws IOException
*/
@Test
public void prefixQueryTest() throws IOException {
String searchField = "title";
Term term = new Term(searchField, "Spar");
Query query = new PrefixQuery(term);
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(query);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
短語(yǔ)搜索
/**
* 短語(yǔ)搜索
* <p>
* 所謂PhraseQuery,就是通過(guò)短語(yǔ)來(lái)檢索,比如我想查“big car”這個(gè)短語(yǔ),
* 那么如果待匹配的document的指定項(xiàng)里包含了"big car"這個(gè)短語(yǔ),
* 這個(gè)document就算匹配成功??扇绻ヅ涞木渥永锇氖恰癰ig black car”,
* 那么就無(wú)法匹配成功了,如果也想讓這個(gè)匹配,就需要設(shè)定slop,
* 先給出slop的概念:slop是指兩個(gè)項(xiàng)的位置之間允許的最大間隔距離
*
* @throws IOException
*/
@Test
public void phraseQueryTest() throws IOException {
String searchField = "content";
String query1 = "apache";
String query2 = "spark";
PhraseQuery.Builder builder = new PhraseQuery.Builder();
builder.add(new Term(searchField, query1));
builder.add(new Term(searchField, query2));
builder.setSlop(0);
PhraseQuery phraseQuery = builder.build();
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(phraseQuery);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
相近詞語(yǔ)搜索
/**
* 相近詞語(yǔ)搜索
* <p>
* FuzzyQuery是一種模糊查詢,它可以簡(jiǎn)單地識(shí)別兩個(gè)相近的詞語(yǔ)。
*
* @throws IOException
*/
@Test
public void fuzzyQueryTest() throws IOException {
String searchField = "content";
Term t = new Term(searchField, "大規(guī)模");
Query query = new FuzzyQuery(t);
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(query);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
通配符搜索
/**
* 通配符搜索
* <p>
* Lucene也提供了通配符的查詢,這就是WildcardQuery。
* 通配符“?”代表1個(gè)字符,而“*”則代表0至多個(gè)字符。
*
* @throws IOException
*/
@Test
public void wildcardQueryTest() throws IOException {
String searchField = "content";
Term term = new Term(searchField, "大*規(guī)模");
Query query = new WildcardQuery(term);
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(query);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
分詞查詢
/**
* 分詞查詢
*
* @throws IOException
* @throws ParseException
*/
@Test
public void queryParserTest() throws IOException, ParseException {
//Analyzer analyzer = new StandardAnalyzer(); // 標(biāo)準(zhǔn)分詞器,適用于英文
//Analyzer analyzer = new SmartChineseAnalyzer();//中文分詞
//Analyzer analyzer = new ComplexAnalyzer();//中文分詞
//Analyzer analyzer = new IKAnalyzer();//中文分詞
Analyzer analyzer = new IKAnalyzer();//中文分詞
String searchField = "content";
//指定搜索字段和分析器
QueryParser parser = new QueryParser(searchField, analyzer);
//用戶輸入內(nèi)容
Query query = parser.parse("計(jì)算引擎");
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(query);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
多個(gè) Field 分詞查詢
/**
* 多個(gè) Field 分詞查詢
*
* @throws IOException
* @throws ParseException
*/
@Test
public void multiFieldQueryParserTest() throws IOException, ParseException {
//Analyzer analyzer = new StandardAnalyzer(); // 標(biāo)準(zhǔn)分詞器,適用于英文
//Analyzer analyzer = new SmartChineseAnalyzer();//中文分詞
//Analyzer analyzer = new ComplexAnalyzer();//中文分詞
//Analyzer analyzer = new IKAnalyzer();//中文分詞
Analyzer analyzer = new IKAnalyzer();//中文分詞
String[] filedStr = new String[]{"title", "content"};
//指定搜索字段和分析器
QueryParser queryParser = new MultiFieldQueryParser(filedStr, analyzer);
//用戶輸入內(nèi)容
Query query = queryParser.parse("Spark");
//執(zhí)行查詢,并打印查詢到的記錄數(shù)
executeQuery(query);
}
響應(yīng)
總共查詢到1個(gè)文檔
id:1
title:Spark
content:Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎!
中文分詞器
/**
* IKAnalyzer 中文分詞器
* SmartChineseAnalyzer smartcn分詞器 需要lucene依賴 且和lucene版本同步
*
* @throws IOException
*/
@Test
public void AnalyzerTest() throws IOException {
//Analyzer analyzer = new StandardAnalyzer(); // 標(biāo)準(zhǔn)分詞器,適用于英文
//Analyzer analyzer = new SmartChineseAnalyzer();//中文分詞
//Analyzer analyzer = new ComplexAnalyzer();//中文分詞
//Analyzer analyzer = new IKAnalyzer();//中文分詞
Analyzer analyzer = null;
String text = "Apache Spark 是專(zhuān)為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎";
analyzer = new IKAnalyzer();//IKAnalyzer 中文分詞
printAnalyzerDoc(analyzer, text);
System.out.println();
analyzer = new ComplexAnalyzer();//MMSeg4j 中文分詞
printAnalyzerDoc(analyzer, text);
System.out.println();
analyzer = new SmartChineseAnalyzer();//Lucene 中文分詞器
printAnalyzerDoc(analyzer, text);
}
三種分詞響應(yīng)
apache spark 專(zhuān)為 大規(guī)模 規(guī)模 模數(shù) 數(shù)據(jù)處理 數(shù)據(jù) 處理 而設(shè) 設(shè)計(jì) 快速 通用 計(jì)算 引擎
apache spark 是 專(zhuān)為 大規(guī)模 數(shù)據(jù)處理 而 設(shè)計(jì) 的 快速 通用 的 計(jì)算 引擎
apach spark 是 專(zhuān) 為 大規(guī)模 數(shù)據(jù) 處理 而 設(shè)計(jì) 的 快速 通用 的 計(jì)算 引擎
高亮處理
/**
* 高亮處理
*
* @throws IOException
*/
@Test
public void HighlighterTest() throws IOException, ParseException, InvalidTokenOffsetsException {
//Analyzer analyzer = new StandardAnalyzer(); // 標(biāo)準(zhǔn)分詞器,適用于英文
//Analyzer analyzer = new SmartChineseAnalyzer();//中文分詞
//Analyzer analyzer = new ComplexAnalyzer();//中文分詞
//Analyzer analyzer = new IKAnalyzer();//中文分詞
Analyzer analyzer = new IKAnalyzer();//中文分詞
String searchField = "content";
String text = "Apache Spark 大規(guī)模數(shù)據(jù)處理";
//指定搜索字段和分析器
QueryParser parser = new QueryParser(searchField, analyzer);
//用戶輸入內(nèi)容
Query query = parser.parse(text);
TopDocs topDocs = indexSearcher.search(query, 100);
// 關(guān)鍵字高亮顯示的html標(biāo)簽,需要導(dǎo)入lucene-highlighter-xxx.jar
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>");
Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
//取得對(duì)應(yīng)的文檔對(duì)象
Document document = indexSearcher.doc(scoreDoc.doc);
// 內(nèi)容增加高亮顯示
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(document.get("content")));
String content = highlighter.getBestFragment(tokenStream, document.get("content"));
System.out.println(content);
}
}
響應(yīng)
<span style='color:red'>Apache</span> <span style='color:red'>Spark</span> 是專(zhuān)為<span style='color:red'>大規(guī)模數(shù)據(jù)處理</span>而設(shè)計(jì)的快速通用的計(jì)算引擎!
代碼我已放到 Github ,導(dǎo)入spring-boot-lucene-demo 項(xiàng)目
github spring-boot-lucene-demo
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
.NET?6開(kāi)發(fā)TodoList應(yīng)用實(shí)現(xiàn)系列背景
這篇文章主要介紹了.NET?6開(kāi)發(fā)TodoList應(yīng)用實(shí)現(xiàn)系列背景,NET?6是一個(gè)很優(yōu)秀的框架,這一點(diǎn)自從我最開(kāi)始接觸.NET?Core?2起一年一年進(jìn)化到現(xiàn)在,就深切地感受到,那好東西就拿出來(lái)和大家分享一下,下面來(lái)看一下文章的學(xué)習(xí)介紹吧2021-12-12
ASP.NET抓取網(wǎng)頁(yè)內(nèi)容的實(shí)現(xiàn)方法
這篇文章主要介紹了ASP.NET抓取網(wǎng)頁(yè)內(nèi)容的實(shí)現(xiàn)方法,涉及使用HttpWebRequest及WebResponse抓取網(wǎng)頁(yè)內(nèi)容的技巧,需要的朋友可以參考下2015-02-02
詳解.net core webapi 前后端開(kāi)發(fā)分離后的配置和部署
這篇文章主要介紹了.net core webapi 前后端開(kāi)發(fā)分離后的配置和部署,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
ASP.NET開(kāi)源導(dǎo)入導(dǎo)出庫(kù)Magicodes.IE完成Csv導(dǎo)入導(dǎo)出的方法
這篇文章主要介紹了ASP.NET開(kāi)源導(dǎo)入導(dǎo)出庫(kù)Magicodes.IE完成Csv導(dǎo)入導(dǎo)出的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
vs2012創(chuàng)建的ado.net模型無(wú)法實(shí)例化的解決方案
本文給大家分享的是升級(jí)vs2012后,發(fā)現(xiàn)創(chuàng)建數(shù)據(jù)模型無(wú)法實(shí)例化使用,嘗試了很多種方法,最后在度娘的幫助下,才解決了這個(gè)問(wèn)題,這里記錄下來(lái),分享給大家。2015-03-03
asp.net 獲取某個(gè)時(shí)間段的星期并以表格形式排列出來(lái)
今天遇到了個(gè)關(guān)于時(shí)間的操作,而作為初學(xué)者的我,并不是很了解時(shí)間函數(shù)的操作,所以就園里問(wèn)了下別人,經(jīng)別人的幫助我自己實(shí)現(xiàn)了如何在某個(gè)時(shí)間段獲取星期。2010-03-03
ASP.NET?MVC5網(wǎng)站開(kāi)發(fā)顯示文章列表(九)
顯示文章列表分兩塊,管理員可以顯示全部文章列表,一般用戶只顯示自己的文章列表。文章列表的顯示采用easyui-datagrid,后臺(tái)需要與之對(duì)應(yīng)的action返回json類(lèi)型數(shù)據(jù),感興趣的小伙伴們可以參考一下2015-09-09
基于.NET中建構(gòu)子中傳遞子對(duì)象的對(duì)象詳解
本篇文章介紹了,基于.NET中建構(gòu)子中傳遞子對(duì)象的對(duì)象詳解。需要的朋友參考下2013-05-05

