4.1使用IndexSearcher进行搜索
Lucene里与搜索相关的api多数都被包含在org.apache.lucene.search中
4.1.2indexSearcher最简单的使用
IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH);
Term t = new Term(“bookname”,女);
Query q = new TermQuery(t);
Hits hits = searcher.search(q);
For(int i=0; i<hits.length(); i++) {
System.out.println(hits.doc(i));
}
Query类表示一个查找请求,此处用TermQuery类对其进行初始化;Hits表示查找结果
Filter:表示对索引中文档集合的过滤器,它使检索在某一个文档集合的子集中进行;
Sort:对索引的结果进行排序的工具;HitCollector:对检索结果进行选择的一个工具,并将选择后的结果保存在其中;
Weight:就是“权重”,表示一次查询时,索引中的某个文档的重要性。
4.2 Hits类详解
如果一次性把10万个Document返回,全保存在某个HashMap中,然后让用户对其进行操作,会比较慢,所以引出缓存机制
4.2.1Hits内部的缓存
第一步就是使用hitDoc(int i)方法从缓存中取出相应的文档,lucene会先判断当前用户需要取出的文档是不是已经超过了缓存的大小,如果是,则先调用getMoreDocs(int min)方法来扩大缓存,然后再从缓存中返回结果
4.3对搜索结果的评分
该评分可以作为自然排序的依据,可以通过field.setBoost(n f)来设置高低,注意:boost值在索引建立的时候已经写入,而不像其他计算得分的因子是在查询时实时得出的,因此,一旦boost值被写入,就不能修改它,除非重写建立文档索引
4.4构建各种lucene内建的query对象
Query本身是一个抽象类,无法获得它的实例,
--------4.4.1和4.4.2都是query得共有特性-------------
4.4.1 toString查看原子查询
4.4.2查询重写与权重
rewriter(IndexReader reader)该方法让所有的非原子查询进行查询重写,转换为原子查询
weight()方法返回一个weight类型对象,这个对象负责保存对文档的权重的计算方式(当进行查询时,每篇文档都会有一个得分,这个得分可以看作室权重和其他因子共同作用的结果)
---------------4.4.3后面的都是各种query搜索-------------------
4.4.3TermQuery词条搜索
一个term对象包括两个信息,分别是词条本身文本内容和词条所在的field信息
4.4.4BooleanQuery布尔搜索
先创建两个TermQuery,在用BooleanClause.Occur.MUST等来做布尔查询
BooleanClause.Occur中有BooleanClause.Occur.MUST, BooleanClause.Occur.MUST_NOT, BooleanClause.Occur.SHOULD三种形式,组合形式如下:
MUST和MUST:取它们结果的交集
MUST和MUST_NOT
MUST_NOT和MUST_NOT:没有意义
SHOULD与MUST,SHOULD与MUST_NOT:SHOULD当与MUST联用时,它失去意义,检索结果为MUST子句的检索结果;当它与MUST_NOT联用时,它的功能就像MUST那样,结果和MUST和MUST_NOT一样
SHOULD和SHOULD:它们表示为一种“或”的关系
query.add(q1,BooleanClause.Occur.MUST);
query.add(q2,BooleanClause.Occur.MUST);
query.add(q3,BooleanClause.Occur.MUST_NOT);可以通过add()添加多个子句
默认最大子句数量为1024,超过会抛出一个TooManyClauses异常,可以通过setMAxClauseCount(int maxClauseCount)更改最大子句数量
4.4.5RangeQuery范围搜索
首先要为query对象设置一个上界和下界
Term begin = new Term(“booknumber”,”0000001”);
Term end = new Term(“booknumber”,”0000005”);
RangeQuery query = new RangeQuery(begin,end,false);布尔值则表示是否将临界值也加入结果中
4.4.6PrefixQuery前缀搜索
Term prefix = new Term(“bookname”,”钢”);
PrefixQuery query = new PrefixQuery(prefix);
4.4.7 PhraseQuery短语搜索
PhraseQuery query = new PhraseQuery();
query.add(new Term(“bookname”,”钢”));
query.add(new Term(“bookname”,”铁”));
•顺序一致,即“钢铁”这个短语的文档
•有时,用户经常会输漏一两个关键字,为了解决这种问题,PhraseQuery提供了一种称为“坡度”的参数,它用于表示词组的两个字间可以插入无关字数的个数,默认值为0可以通过setSlop(int i)来设置坡度,为1则表示可以在词组之间插入一个无关字
4.4.8 MultiPhraseQuery多短语搜索
指定前缀,后缀多个时
MultiPhraseQuery query = new MultiPhraseQuery();
//首先向其中加入要查找的短语的前缀
query.add(new Term(“bookname”,“钢”));
//构建3个Term,作为短语的后缀
Term t1 = new Term(“bookname”,”铁”);
Term t2 = new Term(“bookname”,”和”);
Term t3 = new Term(“bookname”,”要”);
query.add(new Term【】{t1,t2,t3});
指定后缀,前缀多个时
MultiPhraseQuery query = new MultiPhraseQuery();
//首先创建两个term作为前缀
Term t1 = new Term(“bookname”,”铁”);
Term t2 = new Term(“bookname”,”和”);
query.add(new Term【】{t1,t2});
//向其中加入要查找的短语的后缀
query.add(new Term(“bookname”,“钢”));
指定后缀,前缀多个时,在后缀后又多几个后缀
MultiPhraseQuery query = new MultiPhraseQuery();
//首先创建两个term作为前缀
Term t1 = new Term(“bookname”,”铁”);
Term t2 = new Term(“bookname”,”和”);
query.add(new Term【】{t1,t2});
//向其中加入要查找的短语的后缀
query.add(new Term(“bookname”,“钢”));
Term t3 = new Term(“bookname”,”是”);
Term t4= new Term(“bookname”,”战”);
query.add(new Term[]{t3,t4});
4.4.9 FuzzyQuery模糊搜索
模糊查找使用的匹配算法被称为levenshtein算法,这种算法在比较两个字符时,将动作分为三种:加一个字母,删一个字母,改变一个字母。。。在执行将其中一个字串转变为另一个字串的操作,都会相应扣取一定分数,完后的分数被称为两者之间的距离,也叫模糊度
Term t = new Term(“content”,”work”);
FuzzyQuery query = new FuzzyQuery(t,0.1f,1);或者FuzzyQuery query = new FuzzyQuery(t,0.1f)
第二个参数相似度,默认为0.5,值越小,匹配程度越低,数量也多,第三个参数表示所有词条只有第一个字母相符才会放入备选集合中
4.4.10 WildcardQuery通配符搜索
“*”表示0到多个字符,“?”表示一个单一的字符
Term t = new Term(“content”,”?o*”);
WildcardQuery query = new WildcardQuery(t);
4.4.11 SpanQuery跨度搜索
跨度其实就是位置的意思,span指的是一种数据源中每个词条的位置所构成的一个跨度
1,SpanTermQuery
它的效果和TermQuery完全一样
2.SpanFirstQuery
它是在Span和query之间加上一个first
Term t = new Term(“content”,”many”);
SpanTermQuery people = new SpanTermQuery(t);
SpanFirstQuery query = new SpanFirstQuery(people,3);
3.SpanNearQuery
从功能上说,它类似于PhraseQuery,不同的是,PhraseQuery在文档中,所查找的是具有一定无关单词长度的短语,而SpanNearQuery所匹配的不一定是短语,它还有可能将另一个SpanQuery的查询结果作为整体进行考虑
Term t 1= new Term(“content”,”many”);
Term t 2= new Term(“content”,”poor”);
SpanTermQuery people = new SpanTermQuery(t1);
SpanTermQuery how = new SpanTermQuery(t2);
SpanNearQuery query = new SpanNearQuery(new SpanQuery[]{people,how},3,false);,第二个参数是坡度的意思,最后一个参数表示词组中的每一个词是否一定要按照顺序出现在文档中
复杂点如下:
Term t 1= new Term(“content”,”many”);
Term t 2= new Term(“content”,”poor”);
SpanTermQuery people = new SpanTermQuery(t1);
SpanTermQuery how = new SpanTermQuery(t2);
Term t 3= new Term(“content”,”many”);
Term t 4= new Term(“content”,”poor”);
SpanTermQuery people2 = new SpanTermQuery(t3);
SpanTermQuery how 2= new SpanTermQuery(t4);
SpanNearQuery query1 = new SpanNearQuery(new SpanQuery[]{people,how},3,false)
SpanNearQuery query2 = new SpanNearQuery(new SpanQuery[]{people2,how2},3,false)
SpanNearQuery query = new SpanNearQuery(new SpanQuery[]{query1, query2},3,false)第二个参数是坡度的意思,最后一个参数表示词组中的每一个词是否一定要按照顺序出现在文档中
4.SpanOrQuery
SpanOrQuery就是把所有的SpanQuery的结果综合起来,作为它的检索结果,因此它的构造函数包含一个SpanQuery的数组
Term t 1= new Term(“content”,”many”);
Term t 2= new Term(“content”,”poor”);
SpanTermQuery people = new SpanTermQuery(t1);
SpanTermQuery how = new SpanTermQuery(t2);
Term t 3= new Term(“content”,”many”);
Term t 4= new Term(“content”,”poor”);
SpanTermQuery people2 = new SpanTermQuery(t3);
SpanTermQuery how 2= new SpanTermQuery(t4);
SpanNearQuery query1 = new SpanNearQuery(new SpanQuery[]{people,how},3,false)
SpanNearQuery query2 = new SpanNearQuery(new SpanQuery[]{people2,how2},3,false)
SpanOrQuery query = new SpanOrQuery(new SpanQuery[]{query1,query2});
5.SpanNotQuery
SpanNotQuery有两个SpanQuery的参数,它表示,从第一个SpanQuery的查询结果中,去掉第二个SpanQuery的查询结果
4.5第三方提供的Query对象:RegexQuery
String regex = “正则表达式”;
Term t = new Term(“url”,regex);
RegexQuery query = new RegexQuery(t);
注意:1,这个要另外加入第三方的包
4.6通过QueryParser转换用户关键字
4.6.1 QueryParser初始化
String field = “bookname”;
String querystr = “java struts”;
QueryParser parser = new QueryParser(field,new StandardAnalyzer());
Query q = parser.parse(querystr); 默认的为布尔逻辑,既“或”
4.6.2改变QueryParser默认的布尔逻辑
String field = “bookname”;
String querystr = “java struts”;
QueryParser parser = new QueryParser(field,new StandardAnalyzer());
parser.setDafaultOperator(QueryParser.AND_OPERATOR);
Query q = parser.parse(querystr);
也可以不用设置,直接输入
java AND struts
java OR struts
java –struts
java NOT sturts
4.6.3 短语和QueryParser
如果想让QueryParser不对其进行分词,而将其完整地作为一个词条进行处理,需要在词组的外面加上引号:String querystr = “\”god helps those who help themselves\””; 当要设置其坡度值时,,String querystr = “\”god helps those who help themselves\”~1”;即可
4.6.4FuzzyQuery 和QueryParser
该字符串work~0.2,,,,,,既可以使 QueryParser理解其意图,既设置其相似度为“0.2”
4.6.5统配符与 QueryParser
Java str*s java stru?s 即可
4.6.6 查找指定的Field
String querystr = “rome publishdata:2006-09-01”;
QueryParser parser = new QueryParser(“bookname”,new StandardAnalyzer());
parser.setDafaultOperator(QueryParser.AND_OPERTOR);
toString后结果:+bookname:rome +publishdate:2006-09-01
4.6.7RangeQuery 与QueryParser
String querystr = “[1990-01-01 TO 1998-12-01]”;如果为时间的话,它会被转换为字符串,所以在使用lucene时,当遇到日期类型数据,都先使用DateTools(org.apache..lucene.document包下)进行转换,再进行索引
4.6.7 QueryParser和 SpanQuery
不知道支持不支持,,,,,,,
4.7多Field搜索与多索引搜索
4.7.1 多域搜索 MultiFieldQueryParser
MultiFieldQueryParser为了解决在多个不同的Field中检索信息问题,
4.7.2 MultiSearcher 在多个索引上搜索
4.7.3 ParalellMultiSearcher :多线程搜索
当索引的数量越多,它的搜索效率就会越低,,书作者认为是lucene没有为ParalellMultiSearcher开设一个专门的线程池,这样每次都需要实例化新线程,导致性能降低
4.7.4 Searchable 和RMI
Java中RMI 提供了调用远程虚拟机中对象方法的能力,可以通过RMI,获取远程虚拟机中的对象存根Stub,然后调用它的方法,并在远程虚拟机内执行。最后将结果返回本机进行处理,。。。为了应对分布式的搜索,lucene本身也提供了支持RMI的接口(WebService也可以)