Lucene是apache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構(gòu),提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟件開發(fā)人員提供一個簡單易用的工具包,以方便的在目標(biāo)系統(tǒng)中實現(xiàn)全文檢索的功能,或者是以此為基礎(chǔ)建立起完整的全文檢索引擎
全文檢索概述
比如,我們一個文件夾中,或者一個磁盤中有很多的文件,記事本、world、Excel、pdf,我們想根據(jù)其中的關(guān)鍵詞搜索包含的文件。例如,我們輸入Lucene,所有內(nèi)容含有Lucene的文件就會被檢查出來。這就是所謂的全文檢索。
因此,很容易的我們想到,應(yīng)該建立一個關(guān)鍵字與文件的相關(guān)映射,盜用ppt中的一張圖,很明白的解釋了這種映射如何實現(xiàn)。
倒排索引
有了這種映射關(guān)系,我們就來看看Lucene的架構(gòu)設(shè)計。
下面是Lucene的資料必出現(xiàn)的一張圖,但也是其精髓的概括。
我們可以看到,Lucene的使用主要體現(xiàn)在兩個步驟:
1 創(chuàng)建索引,通過IndexWriter對不同的文件進(jìn)行索引的創(chuàng)建,并將其保存在索引相關(guān)文件存儲的位置中。
2 通過索引查尋關(guān)鍵字相關(guān)文檔。
在Lucene中,就是使用這種“倒排索引”的技術(shù),來實現(xiàn)相關(guān)映射。
Lucene數(shù)學(xué)模型
文檔、域、詞元
文檔是Lucene搜索和索引的原子單位,文檔為包含一個或者多個域的容器,而域則是依次包含“真正的”被搜索的內(nèi)容,域值通過分詞技術(shù)處理,得到多個詞元。
For Example,一篇小說(斗破蒼穹)信息可以稱為一個文檔,小說信息又包含多個域,例如:標(biāo)題(斗破蒼穹)、作者、簡介、最后更新時間等等,對標(biāo)題這個域采用分詞技術(shù)又可以得到一個或者多個詞元(斗、破、蒼、穹)。
Lucene文件結(jié)構(gòu)
層次結(jié)構(gòu)
index
一個索引存放在一個目錄中
segment
一個索引中可以有多個段,段與段之間是獨立的,添加新的文檔可能產(chǎn)生新段,不同的段可以合并成一個新段
document
文檔是創(chuàng)建索引的基本單位,不同的文檔保存在不同的段中,一個段可以包含多個文檔
field
域,一個文檔包含不同類型的信息,可以拆分開索引
term
詞,索引的最小單位,是經(jīng)過詞法分析和語言處理后的數(shù)據(jù)。
正向信息
按照層次依次保存了從索引到詞的包含關(guān)系:index-->segment-->document-->field-->term。
反向信息
反向信息保存了詞典的倒排表映射:term-->document
IndexWriter
lucene中最重要的的類之一,它主要是用來將文檔加入索引,同時控制索引過程中的一些參數(shù)使用。
Analyzer
分析器,主要用于分析搜索引擎遇到的各種文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。
Directory
索引存放的位置;lucene提供了兩種索引存放的位置,一種是磁盤,一種是內(nèi)存。一般情況將索引放在磁盤上;相應(yīng)地lucene提供了FSDirectory和RAMDirectory兩個類。
Document
文檔;Document相當(dāng)于一個要進(jìn)行索引的單元,任何可以想要被索引的文件都必須轉(zhuǎn)化為Document對象才能進(jìn)行索引。
Field
字段。
IndexSearcher
是lucene中最基本的檢索工具,所有的檢索都會用到IndexSearcher工具;
Query
查詢,lucene中支持模糊查詢,語義查詢,短語查詢,組合查詢等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些類。
QueryParser
是一個解析用戶輸入的工具,可以通過掃描用戶輸入的字符串,生成Query對象。
Hits
在搜索完成之后,需要把搜索結(jié)果返回并顯示給用戶,只有這樣才算是完成搜索的目的。在lucene中,搜索的結(jié)果的集合是用Hits類的實例來表示的。
測試用例
Github 代碼
代碼我已放到 Github ,導(dǎo)入spring-boot-lucene-demo 項目
github spring-boot-lucene-demo
添加依賴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<!--對分詞索引查詢解析--> < 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
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)建一個索引的查找器,來檢索索引庫 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 + "個文檔" ); for (ScoreDoc scoreDoc : topDocs.scoreDocs) { //取得對應(yīng)的文檔對象 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)建索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
@Test public void indexWriterTest() throws IOException { long start = System.currentTimeMillis(); //索引存放的位置,設(shè)置在當(dāng)前目錄中 Directory directory = FSDirectory.open(Paths.get( "indexDir/" )); //在 6.6 以上版本中 version 不再是必要的,并且,存在無參構(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)建索引寫入配置 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); //創(chuàng)建索引寫入對象 IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); //創(chuàng)建Document對象,存儲索引 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 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎" , Field.Store.YES)); doc.add( new StoredField( "id" , id)); //將doc對象保存到索引庫中 indexWriter.addDocument(doc); indexWriter.commit(); //關(guān)閉流 indexWriter.close(); long end = System.currentTimeMillis(); System.out.println( "索引花費了" + (end - start) + " 毫秒" ); } |
響應(yīng)
1
2
3
|
17:58:14.655 [main] DEBUG org.wltea.analyzer.dic.Dictionary - 加載擴展詞典:ext.dic 17:58:14.660 [main] DEBUG org.wltea.analyzer.dic.Dictionary - 加載擴展停止詞典:stopword.dic 索引花費了879 毫秒 |
刪除文檔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@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)建索引寫入配置 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); //創(chuàng)建索引寫入對象 IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); // 刪除title中含有關(guān)鍵詞“Spark”的文檔 long count = indexWriter.deleteDocuments( new Term( "title" , "Spark" )); // 除此之外IndexWriter還提供了以下方法: // DeleteDocuments(Query query):根據(jù)Query條件來刪除單個或多個Document // DeleteDocuments(Query[] queries):根據(jù)Query條件來刪除單個或多個Document // DeleteDocuments(Term term):根據(jù)Term來刪除單個或多個Document // DeleteDocuments(Term[] terms):根據(jù)Term來刪除單個或多個Document // DeleteAll():刪除所有的Document //使用IndexWriter進(jìn)行Document刪除操作時,文檔并不會立即被刪除,而是把這個刪除動作緩存起來,當(dāng)IndexWriter.Commit()或IndexWriter.Close()時,刪除操作才會被真正執(zhí)行。 indexWriter.commit(); indexWriter.close(); System.out.println( "刪除完成:" + count); } |
響應(yīng)
刪除完成:1
更新文檔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
/** * 測試更新 * 實際上就是刪除后新增一條 * * @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)建索引寫入配置 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); //創(chuàng)建索引寫入對象 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 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎" , 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
按詞條搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 按詞條搜索 * <p> * TermQuery是最簡單、也是最常用的Query。TermQuery可以理解成為“詞條搜索”, * 在搜索引擎中最基本的搜索就是在索引中搜索某一詞條,而TermQuery就是用來完成這項工作的。 * 在Lucene中詞條是最基本的搜索單位,從本質(zhì)上來講一個詞條其實就是一個名/值對。 * 只不過這個“名”是字段名,而“值”則表示字段中所包含的某個關(guān)鍵字。 * * @throws IOException */ @Test public void termQueryTest() throws IOException { String searchField = "title" ; //這是一個條件查詢的api,用于添加條件 TermQuery query = new TermQuery( new Term(searchField, "Spark" )); //執(zhí)行查詢,并打印查詢到的記錄數(shù) executeQuery(query); } |
響應(yīng)
總共查詢到1個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
多條件查詢
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/** * 多條件查詢 * * BooleanQuery也是實際開發(fā)過程中經(jīng)常使用的一種Query。 * 它其實是一個組合的Query,在使用時可以把各種Query對象添加進(jìn)去并標(biāo)明它們之間的邏輯關(guān)系。 * BooleanQuery本身來講是一個布爾子句的容器,它提供了專門的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)系的類, // 包 括: // BooleanClause.Occur.MUST, // BooleanClause.Occur.MUST_NOT, // BooleanClause.Occur.SHOULD。 // 必須包含,不能包含,可以包含三種.有以下6種組合: // // 1.MUST和MUST:取得連個查詢子句的交集。 // 2.MUST和MUST_NOT:表示查詢結(jié)果中不能包含MUST_NOT所對應(yīng)得查詢子句的檢索結(jié)果。 // 3.SHOULD與MUST_NOT:連用時,功能同MUST和MUST_NOT。 // 4.SHOULD與MUST連用時,結(jié)果為MUST子句的檢索結(jié)果,但是SHOULD可影響排序。 // 5.SHOULD與SHOULD:表示“或”關(guān)系,最終檢索結(jié)果為所有檢索子句的并集。 // 6.MUST_NOT和MUST_NOT:無意義,檢索無結(jié)果。 builder.add(query1, BooleanClause.Occur.SHOULD); builder.add(query2, BooleanClause.Occur.SHOULD); BooleanQuery query = builder.build(); //執(zhí)行查詢,并打印查詢到的記錄數(shù) executeQuery(query); } |
響應(yīng)
總共查詢到1個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
匹配前綴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 匹配前綴 * <p> * PrefixQuery用于匹配其索引開始以指定的字符串的文檔。就是文檔中存在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個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
短語搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/** * 短語搜索 * <p> * 所謂PhraseQuery,就是通過短語來檢索,比如我想查“big car”這個短語, * 那么如果待匹配的document的指定項里包含了"big car"這個短語, * 這個document就算匹配成功。可如果待匹配的句子里包含的是“big black car”, * 那么就無法匹配成功了,如果也想讓這個匹配,就需要設(shè)定slop, * 先給出slop的概念:slop是指兩個項的位置之間允許的最大間隔距離 * * @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個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
相近詞語搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 相近詞語搜索 * <p> * FuzzyQuery是一種模糊查詢,它可以簡單地識別兩個相近的詞語。 * * @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個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
通配符搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 通配符搜索 * <p> * Lucene也提供了通配符的查詢,這就是WildcardQuery。 * 通配符“?”代表1個字符,而“*”則代表0至多個字符。 * * @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個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
分詞查詢
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/** * 分詞查詢 * * @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( "計算引擎" ); //執(zhí)行查詢,并打印查詢到的記錄數(shù) executeQuery(query); } |
響應(yīng)
總共查詢到1個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
多個 Field 分詞查詢
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/** * 多個 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個文檔
id:1
title:Spark
content:Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎!
中文分詞器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/** * 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 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計的快速通用的計算引擎" ; 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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
apache spark 專為 大規(guī)模 規(guī)模 模數(shù) 數(shù)據(jù)處理 數(shù)據(jù) 處理 而設(shè) 設(shè)計 快速 通用 計算 引擎 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
apache spark 是 專為 大規(guī)模 數(shù)據(jù)處理 而 設(shè)計 的 快速 通用 的 計算 引擎 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apach spark 是 專 為 大規(guī)模 數(shù)據(jù) 處理 而 設(shè)計 的 快速 通用 的 計算 引擎 |
高亮處理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
/** * 高亮處理 * * @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) { //取得對應(yīng)的文檔對象 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> 是專為<span style='color:red'>大規(guī)模數(shù)據(jù)處理</span>而設(shè)計的快速通用的計算引擎!
代碼我已放到 Github ,導(dǎo)入spring-boot-lucene-demo 項目
github spring-boot-lucene-demo
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。