欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Lucene-2.2.0 源代碼閱讀學習(32)

系統(tǒng) 1695 0

關于SpanQuery(跨度搜索),它是Query的子類,但是SpanQuery仍然是一個抽象類,它有6個直接子類實現(xiàn)類。繼承關系如圖所示:

Lucene-2.2.0 源代碼閱讀學習(32)

其中SpanTermQuery是一個最基礎的跨度搜索實現(xiàn)類,SpanTermQuery與SpanQuery的關系,就如同TermQuery與Query的關系:SpanTermQuery是為SpanQuery其它的具體實現(xiàn)子類服務的,其實TermQuery也是為Query的具體子類實現(xiàn)類服務的,例如構造一個BooleanQuery查詢,可以向其中添加多個TermQuery查詢子句。

SpanTermQuery跨度搜索

SpanTermQuery的應用與TermQuery的用法是一樣的,獲取到的檢索結果集也是相同的。

這里,SpanTermQuery是SpanQuery的子實現(xiàn)類,所有從跨度搜索的角度來說,他的跨度值就是使用SpanTermQuery的唯一的一個構造方法所用的一個Term的跨度值。也就是說,它的起始位置和結束位置都是一個固定的值(其實就是一個固定跨度)。

SpanFirstQuery跨度搜索

SpanFirstQuery搜索是基于SpanTermQuery的,在實例化一個SpanFirstQuery的時候,是通過一個SpanTermQuery的實例作為參數(shù)來構造的。

該SpanFirstQuery只有唯一的一個構造方法:

public SpanFirstQuery(SpanQuery match, int end) {
??? this.match = match;
??? this.end = end;
}

上面的end指定了在查詢時,從起始位置開始(起始位置為0,這點可以在后面的測試中得知。因為名稱中First已經(jīng)表達了這層含義),在小于end的位置之前的文本中,與match進行匹配。

先使用ThesaurusAnalyzer分析器來實現(xiàn)分詞,為指定的數(shù)據(jù)建立索引,如下所示:

package org.apache.lucene.shirdrn.main;

import java.io.IOException;

import net.teamhot.lucene.ThesaurusAnalyzer;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.LockObtainFailedException;

public class MySearchEngineUsingThesaurusAnalyzer {

public static void main(String[] args){
?? String indexPath = "E:\\Lucene\\index";
?? IndexWriter writer;
?? try {
??? writer = new IndexWriter(indexPath,new ThesaurusAnalyzer(),true);
??? Field fieldA = new Field("contents","今天是我們地球的生日,對于我們每個人,在我們的宇宙中,一場空前關于我們熟悉的宇宙論的辯論激烈地展開了。",Field.Store.YES,Field.Index.TOKENIZED);
??? Document docA = new Document();
??? docA.add(fieldA);
???
??? Field fieldB1 = new Field("contents","誰知道宇宙空間的奧秘,在我們這些人當中?",Field.Store.YES,Field.Index.TOKENIZED);
??? Field fieldB2 = new Field("contents","宇宙飛船。",Field.Store.YES,Field.Index.TOKENIZED);
??? Field fieldB3 = new Field("contents","我們的太空宇宙。",Field.Store.YES,Field.Index.TOKENIZED);
??? Document docB = new Document();
??? docB.add(fieldB1);
??? docB.add(fieldB2);
??? docB.add(fieldB3);
???
??? Field fieldC = new Field("contents","我們宇宙學家對地球的重要性。",Field.Store.YES,Field.Index.TOKENIZED);
??? Document docC = new Document();
??? docC.add(fieldC);
???
??? writer.addDocument(docA);
??? writer.addDocument(docB);
??? writer.addDocument(docC);
??? writer.close();
?? } catch (CorruptIndexException e) {
??? e.printStackTrace();
?? } catch (LockObtainFailedException e) {
??? e.printStackTrace();
?? } catch (IOException e) {
??? e.printStackTrace();
?? }
}

首先要把ThesaurusAnalyzer分析器的jar包加入到CLASSPATH中,然后運行上面的主函數(shù),建立索引。

建立的索引文件在本地磁盤指定的索引目錄E:\Lucene\index下生成,這時候可以測試SpanFirstQuery的使用了。

因為ThesaurusAnalyzer分析器自帶了一個詞庫,該詞庫中有詞條“我們”,我們就通過“我們”來構造SpanQuery,進行查詢。

編寫一個SpanFirstQuerySearcher測試類,帶主函數(shù),如下所示:

package org.apache.lucene.shirdrn.main;

import java.io.IOException;
import java.util.Date;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.spans.SpanFirstQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery;

public class SpanFirstQuerySearcher {

public static void main(String[] args) {
?? String indexPath = "E:\\Lucene\\index";
?? try {
??? IndexSearcher searcher = new IndexSearcher(indexPath);
??? String keyword = "我們";
??? Term term = new Term("contents",keyword);
??? SpanTermQuery spanTermQuery = new SpanTermQuery(term);
??
int end = 1;
??? SpanQuery spanFirstQuery = new SpanFirstQuery(spanTermQuery,end);
??? System.out.println("####################################################################");
??? System.out.println("SpanFirstQuery中end指定值為 : "+end);
??? System.out.println("####################################################################");
??? Date startTime = new Date();
??? Hits hits = searcher.search(spanFirstQuery);
??? for(int i=0;i<hits.length();i++){
???? TermDocs termDocs = searcher.getIndexReader().termDocs(term);
???? while(termDocs.next()){
????? if(termDocs.doc() == hits.id(i)){
?????? System.out.println("Document的內部編號為 : "+hits.id(i));
?????? Document doc = hits.doc(i);
?????? System.out.println("Document的得分為 : "+hits.score(i));
?????? List fieldList = doc.getFields();
?????? System.out.println("Document(編號) "+hits.id(i)+" 的Field的信息: ");
?????? for(int j=0;j<fieldList.size();j++){
??????? Field field = (Field)fieldList.get(j);
??????? System.out.println("??? Field的name : "+field.name());
??????? System.out.println("??? Field的stringValue : "+field.stringValue());
??????? System.out.println("??? ------------------------------------");
?????? }
?????? System.out.println("搜索的該關鍵字【"+keyword+"】在Document(編號) "+hits.id(i)+" 中,出現(xiàn)過 "+termDocs.freq()+" 次");
????? }
???? }
??? }
??? System.out.println("********************************************************************");
??? Date finishTime = new Date();
??? long timeOfSearch = finishTime.getTime() - startTime.getTime();
??? System.out.println("本次搜索所用的時間為 "+timeOfSearch+" ms");
???
?? } catch (CorruptIndexException e) {
??? e.printStackTrace();
?? } catch (IOException e) {
??? e.printStackTrace();
?? }
}
}

當end=1時,也就是從具有一個詞條的跨度,運行結果如下所示:

####################################################################
SpanFirstQuery中end指定值為 : 1
####################################################################
Document的內部編號為 : 2
Document的得分為 : 0.18888181
Document(編號) 2 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 我們宇宙學家對地球的重要性。
??? ------------------------------------
搜索的該關鍵字【我們】在Document(編號) 2 中,出現(xiàn)過 1 次
********************************************************************
本次搜索所用的時間為 78 ms

這里docB沒有被檢索出來。

當end=5時,增大了跨度,執(zhí)行結果如下所示:

####################################################################
SpanFirstQuery中end指定值為 : 5
####################################################################
Document的內部編號為 : 2
Document的得分為 : 0.18888181
Document(編號) 2 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 我們宇宙學家對地球的重要性。
??? ------------------------------------
搜索的該關鍵字【我們】在Document(編號) 2 中,出現(xiàn)過 1 次
Document的內部編號為 : 0
Document的得分為 : 0.09444091
Document(編號) 0 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 今天是我們地球的生日,對于我們每個人,在我們的宇宙中,一場空前關于我們熟悉的宇宙論的辯論激烈地展開了。
??? ------------------------------------
搜索的該關鍵字【我們】在Document(編號) 0 中,出現(xiàn)過 4 次
********************************************************************
本次搜索所用的時間為 62 ms

當end=10的時候,可以看到3個Document都被檢索到,如下所示:

####################################################################
SpanFirstQuery中end指定值為 : 10
####################################################################
Document的內部編號為 : 2
Document的得分為 : 0.18888181
Document(編號) 2 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 我們宇宙學家對地球的重要性。
??? ------------------------------------
搜索的該關鍵字【我們】在Document(編號) 2 中,出現(xiàn)過 1 次
Document的內部編號為 : 0
Document的得分為 : 0.13355961
Document(編號) 0 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 今天是我們地球的生日,對于我們每個人,在我們的宇宙中,一場空前關于我們熟悉的宇宙論的辯論激烈地展開了。
??? ------------------------------------
搜索的該關鍵字【我們】在Document(編號) 0 中,出現(xiàn)過 4 次
Document的內部編號為 : 1
Document的得分為 : 0.1259212
Document(編號) 1 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 誰知道宇宙空間的奧秘,在我們這些人當中?
??? ------------------------------------
??? Field的name : contents
??? Field的stringValue : 宇宙飛船。
??? ------------------------------------
??? Field的name : contents
??? Field的stringValue : 我們的太空宇宙。
??? ------------------------------------
搜索的該關鍵字【我們】在Document(編號) 1 中,出現(xiàn)過 2 次
********************************************************************
本次搜索所用的時間為 234 ms

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

SpanNearQuery跨度搜索

SpanNearQuery只有一個構造方法,可以從SpanNearQuery的構造方法來看:

public SpanNearQuery(SpanQuery[] clauses, int slop, boolean inOrder) {
??? this.clauses = new ArrayList(clauses.length);
??? for (int i = 0; i < clauses.length; i++) {
????? SpanQuery clause = clauses[i];
????? if (i == 0) {?????????????????????????????
??????? field = clause.getField();
????? } else if (!clause.getField().equals(field)) {
??????? throw new IllegalArgumentException("Clauses must have same field.");
????? }
????? this.clauses.add(clause);
??? }

??? this.slop = slop;
??? this.inOrder = inOrder;
}

從方法的聲明來看,各個參數(shù)如下:

clauses是指:一個SpanQuery的子句的數(shù)組;

slop是指:對于每個SpanQuery都由一個Term構造而成,在一段文本中,可能在出現(xiàn)的這兩個詞條之間由若干個其它不相關的詞條,slop指定了一個整數(shù)值,從而可以忽略這些不相關的詞條(忽略的個數(shù)<=slop),如果slop=0,則說明clauses中的SpanQuery查詢的詞條必須是相連著的;

inOrder是指:是否clauses子句們按照有序的方式實現(xiàn)搜索,當inOrder為true時,必須按照各個子句中檢索的詞條的前后順序進行匹配,逆序的就被淘汰。

依然用上面建立的索引文件測試。

測試通過先構造一個SpanTermQuery(詞條內容為“我們”)和一個SpanFirstQuery(詞條內容為“宇宙”),再構造一個SpanNearQuery,測試代碼如下所示:

package org.apache.lucene.shirdrn.main;

import java.io.IOException;
import java.util.Date;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.spans.SpanFirstQuery;
import org.apache.lucene.search.spans.SpanNearQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery;

public class SpanNearQuerySearcher {

public static void main(String[] args) {
?? String indexPath = "E:\\Lucene\\index";
?? try {
??? IndexSearcher searcher = new IndexSearcher(indexPath);
??? String keywordA = "我們";
??? Term termA = new Term("contents",keywordA);
??? SpanTermQuery spanTermQueryA = new SpanTermQuery(termA);???
??? int end = 10;
??? System.out.println("####################################################################");
??? System.out.println("SpanFirstQuery中end指定值為 : "+end);
??? System.out.println("####################################################################");
??? SpanQuery spanFirstQuery = new SpanFirstQuery(spanTermQueryA,end);
??? String keywordB = "宇宙";
??? Term termB = new Term("contents",keywordA);
??? SpanTermQuery spanTermQueryB = new SpanTermQuery(termB);
??? int slop = 2;
??? System.out.println("####################################################################");
??? System.out.println("SpanNearQuery中slop指定值為 : "+slop);
??? System.out.println("####################################################################");
?? SpanNearQuery spanNearQuery = new SpanNearQuery(new SpanQuery[]{spanFirstQuery,spanTermQueryB},slop,true);
??? Date startTime = new Date();
??? Hits hits = searcher.search(spanNearQuery);
??? for(int i=0;i<hits.length();i++){
???? System.out.println("Document的內部編號為 : "+hits.id(i));
???? Document doc = hits.doc(i);
???? System.out.println("Document的得分為 : "+hits.score(i));
???? List fieldList = doc.getFields();
???? System.out.println("Document(編號) "+hits.id(i)+" 的Field的信息: ");
???? for(int j=0;j<fieldList.size();j++){
????? Field field = (Field)fieldList.get(j);
????? System.out.println("??? Field的name : "+field.name());
????? System.out.println("??? Field的stringValue : "+field.stringValue());
????? System.out.println("??? ------------------------------------");
???? }
??? }
??? System.out.println("********************************************************************");
??? Date finishTime = new Date();
??? long timeOfSearch = finishTime.getTime() - startTime.getTime();
??? System.out.println("本次搜索所用的時間為 "+timeOfSearch+" ms");
???
?? } catch (CorruptIndexException e) {
??? e.printStackTrace();
?? } catch (IOException e) {
??? e.printStackTrace();
?? }
}
}

這里,指定了slop=2,inOrder=true,即:“我們”和“宇宙”是按先后順序在Document中進行匹配的。

運行測試程序,結果如下:

####################################################################
SpanFirstQuery中end指定值為 : 10
####################################################################
####################################################################
SpanNearQuery中slop指定值為 : 2
####################################################################
Document的內部編號為 : 0
Document的得分為 : 0.059729677
Document(編號) 0 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 今天是我們地球的生日,對于我們每個人,在我們的宇宙中,一場空前關于我們熟悉的宇宙論的辯論激烈地展開了。
??? ------------------------------------
********************************************************************
本次搜索所用的時間為 93 ms

其實,我們指定了SpanFirstQuery足夠大的跨度,但是在SpanNearQuery中指定的slop的值很小,在進行匹配的時候,只是允許兩個詞條之間可以有2個無關的其它詞條,再加上指定了inOrder為true,嚴格有序,所以只檢索到了編號為0的Document。

現(xiàn)在,將slop改為10,因為slop比較關鍵,決定了兩個檢索詞條之間的間隙大小,這時可以看到檢索結果如下所示:

####################################################################
SpanFirstQuery中end指定值為 : 10
####################################################################
####################################################################
SpanNearQuery中slop指定值為 : 10
####################################################################
Document的內部編號為 : 0
Document的得分為 : 0.078204505
Document(編號) 0 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 今天是我們地球的生日,對于我們每個人,在我們的宇宙中,一場空前關于我們熟悉的宇宙論的辯論激烈地展開了。
??? ------------------------------------
Document的內部編號為 : 1
Document的得分為 : 0.06730772
Document(編號) 1 的Field的信息:
??? Field的name : contents
??? Field的stringValue : 誰知道宇宙空間的奧秘,在我們這些人當中?
??? ------------------------------------
??? Field的name : contents
??? Field的stringValue : 宇宙飛船。
??? ------------------------------------
??? Field的name : contents
??? Field的stringValue : 我們的太空宇宙。
??? ------------------------------------
********************************************************************
本次搜索所用的時間為 125 ms

SpanNearQuery的構造方法給了一個SpanQuery[] clauses子句數(shù)組,可以使用任何繼承了SpanQuery的具體實現(xiàn)類,當然也包括SpanNearQuery,將它們添加到子句的數(shù)組中,實現(xiàn)復雜的搜索。

SpanNotQuery跨度搜索

依然從構造方法看:

public SpanNotQuery(SpanQuery include, SpanQuery exclude) {
??? this.include = include;
??? this.exclude = exclude;

??? if (!include.getField().equals(exclude.getField()))
????? throw new IllegalArgumentException("Clauses must have same field.");
}

該SpanNotQuery指定了一個SpanQuery include,該include子句查詢會得到一個結果的集合,設為集合A;SpanQuery exclude也可以得到一個結果的集合,設為集合B,則SpanNotQuery檢索結果的集合表示為:

A-B

很好理解,就是集合的差運算。

SpanOrQuery跨度搜索

這個也很好理解,就是集合的并運算,它的構造方法如下所示:

public SpanOrQuery(SpanQuery[] clauses) {

??? this.clauses = new ArrayList(clauses.length);
??? for (int i = 0; i < clauses.length; i++) {
????? SpanQuery clause = clauses[i];
????? if (i == 0) {???????????????????????????????
??????? field = clause.getField();
????? } else if (!clause.getField().equals(field)) {
??????? throw new IllegalArgumentException("Clauses must have same field.");
????? }
????? this.clauses.add(clause);
??? }
}

只要把你想要檢索的SpanQuery子句構造好以后,添加到SpanQuery[] clauses數(shù)組中,談后執(zhí)行SpanOrQuery跨度搜索的時候,會把每個子句得到的結果合并起來,得到一個很龐大的檢索結果集。

SpanRegexQuery跨度搜索

構造該SpanQuery也很容易:

public SpanRegexQuery(Term term) {
??? this.term = term;
}

只需要一個Term作為參數(shù)即可。從該SpanRegexQuery的名稱來看,就知道它和正則表達式有一定的聯(lián)系。其實在構造好一個SpanRegexQuery以后,可以為其設置一個正則表達式,這要看你對正則表達式的運用的熟練程度如何了。

在SpanRegexQuery中定義了兩個成員變量:

private RegexCapabilities regexImpl = new JavaUtilRegexCapabilities();
private Term term;

而且SpanRegexQuery實現(xiàn)了RegexQueryCapable接口:

public class SpanRegexQuery extends SpanQuery implements RegexQueryCapable

如果你想使用SpanRegexQuery實現(xiàn)跨度搜索,可以研究一下與SpanRegexQuery相關的JavaUtilRegexCapabilities類,在JavaUtilRegexCapabilities中涉及到了java.util.regex.Pattern,它可不是Lucene定義的,是第三方提供的。

Lucene-2.2.0 源代碼閱讀學習(32)


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 天天插天天射天天干 | 开心深爱激情 | 偷拍亚洲制服另类无码专区 | 国产成人免费无庶挡视频 | 女人一级毛片免费视频观看 | 国产亚洲精品综合在线网址 | 特级毛片8级毛片免费观看 亚洲精品不卡 | 亚洲精品欧美一区二区三区 | 日韩第一页在线 | 国产毛片视频 | 亲爱的热爱的电视剧免费观看 | 色婷婷色 | 免费久久网站 | 亚洲成人精品 | 日韩无套 | 性欧美精品久久久久久久 | 久久国产这里只精品免费 | 国产日韩精品一区 | 日日久| 国产肝交视频在线观看 | www国产精品| 欧美视频在线免费播放 | 欧美日批视频 | 日韩欧美一区二区三区免费观看 | 亚洲综合久久成人A片红豆 日本亚洲成人 | 波多野结衣视频免费观看 | 久久久在线 | 欧美日剧在线免费 | 成人免费网站视频 | 嫩草影院在线入口 | 欧美黄色一区 | 狠狠久 | 黄色资源视频 | 日韩视频一| av福利在线观看 | 精品一区二区三区四区五区 | 精品一区二区三区水蜜桃 | 国产乱仑 | 一级毛片一级毛片一级毛片 | 人人人人干| 久久久久久久 |