1、 初始化IndexSearcher :Searcher searcher = new IndexSearcher(indexDir);//indexDir为索引存放路径
2、 生成Query对象: QueryParser类的parse()方法返回Query类形对象
3、 使用search(Query)方法,开始搜索,并返回Hits对象
4、 使用Hits对象的方法检索结果:
length();//结果总数量
doc(int n);//返回第n个文档;Document对象
id(int n);//第n个文档的内部ID
score(n);//第n个文档的分值,用于排序
例子:
IndexSearcher searcher = new IndexSearcher(“c://index”);
Query query = QueryParser.parse(“key1”,”name”,new StandardAnalyzer());
Hits hits = searcher.search(query);
If(hits.length()==0){
Out.println(“not found”);
}
else{
for(int i=0;i Document d = hits.doc(i);
Out.println(d.get(“title”));
}
}
文档搜索结果的主要排序依据是文档的分值。改变文档分值的方法是建立索引时,在初始化Document对象后,使用Document的setBoost方法来改变文档的boost因子(分值的倍数):
Document doc = new Document();
Doc.add(Field.Text(“contents”,”text1 text2”));
Doc.setBoost(1.5f); //改变因子,如0.3f,1.0f等
构建Query:
Query是search包中的一个抽象类,它有许多子类,代表不同类形的查询
关键字TermQuery
Term term = new Term(“contents”,”java”);//实质也是一个键/值对
//构造TermQuery
Query query = new TermQuery(term);
组合查询BooleanQuery
BooleanQuery是一个查询容器,提供专门的方法往其中加入查询,并标明条件的关系
IndexSearcher searcher = new IndexSearcher(“c://index”);
Query q1 = new TermQuery(new Term(“name”,”tim”));
Query q2 = new TermQuery(new Term(“name”,”fly”));
//构造容器
Query query = new BooleanQuery();
query.add(q1,true,false);
query..add(q2,true,false);
Hits hits = searcher.search(query);
BooleanQuery的add方法的第二,第三参数说明:第二参数表示是否必须满足,第三参数表示是否不需要满足,组合一起有以下三种情况:
True,false:当前查询条件是必须要满足的
False ,true:当前查询是不可以满足的
False,false:条件是可选的
True,true:这种情况是错误的
以上表明,上述例子的两个条件都是必须满足的,是“与(and)”的关系
如果查进行“或(or)”运算,相应地可改为:
query.add(q1,false,false);
query.add(q2,false,false)
范围搜索RangeQuery
RangeQuery query = new RangeQuery(begin,end,included);//最后参数为是否包含边界
例:
Term begin = new Term(“time”,”20050101”);
Term end = new Term(“time”,”20050202”);
RangeQuery query = new RangeQuery(begin,end,false);
前缀PrefixQuery
PrefixQuery query = new PrefixQuery(new Term(“name”,”ti”));//name字段中以ti开头
多关键字PhraseQuery
PhraseQuery query = new PhraseQuery();
Query.add(new Term(“content”,”hello”));
Query.add(new Term(“content”,”world”));
Query.setSlop(2);
//设置以上加上的两个关键字坡度,此值代表两个关键字之间无关词的个数.对于两个紧连的关键字,无论将坡度设为多少都能找到,如果两个词不紧连,且坡度值小于它们之间的无关词的数量,则无法找到
短词缀PhrasePrefixQuery
Term word1 = new Term(“content”,”david”);
Term word2 = new Term(“content”,”mary”);
Term word3 = new Term(“content”,”robert”);
PhrasePrefixQuery query = new PhrasePrefixQuery();
//加入不确定的词
Query.add(new Term[]{word1,word2});//不确定,第一个关键词在Term数组中产生
//加入确定的词
query.add(word3);
query.setSlop(2);//设置坡度
//以上查询中,david robert和mary robert都会出现在查询结果,同样地,mary and robert也会被击中
相近词FuzzyQuery
FuzzyQuery query = new FuzzyQuery(new Term(“content”,”david”));
通配符WildcardQuery
WildcardQuery query = new WildcardQuery(new Term(“content”,”*im”));
WildcardQuery query = new WildcardQuery(new Term(“content”,”t?m??”));
//*代表0个或多个字符,?一个字符
QueryParser类,把用户各种输入转为Query
Query query = QueryParser.parse(keywords,filedName,new StandardAnalyer());
关键字格式:
“tim” //在默认字段搜索tim
“name:tim”;//在name字段搜tim
“tim wong”或tim or wong;//在默认字段搜搜关键字tim 或wong
“+tim +wong”或”tim and wong” //搜索tim和 wong
”tim*”//在默认字段中搜前缀为tim的
“name:tim is a programer”;//在name字段中包含短语tim is a programer
“(tim or wong) and php” //在默认字段中搜含有tim 或wong的关键字,但一定要包含php
“name:tim –title:php” //name字段搜tim,并且title不含有php
另外,QueryParser构造时需要一个分析器,它应该与建立索引时的分析器一样
QueryParser的“与”和“或”
当输入两个关键字时,默认关系是或,要改变这种关系,方法是:
QueryParser parser = new QueryParser(keyword,fieldNmae,new StandardAnalyzer());
Parser.setOperator(QueryParser.DEFAULT_OPERATOR_AND);
排序及多字段查找
默认情况下,IndexSearcher类的search方法返回查询结果时,是按文档的分值排序的,可以使用重载的search方法对结果排序
IndexSearcher.search(Query,Sort);
new Sort() 和 Sort.RELEVANCE,以及null一样,采用默认排序,要定义排序字段,方法是将字段传入Sort对象
Sort sort = new Sort(String field);
也可以对多个字段排序Sort sort = new Sort(String[] fields);
例:
Sort sort = new Sort(new SortField[]{new SortField(“title”),new SortField(“name”)});
Hits hits=searcher.search(query,Sort);
多字段查找MultiFieldQueryParser
只在某些Term中查找,不关心在哪个字段
Query query = new MultiFieldQueryParser.parse(“word”,new String[]{“title”,”content”},analyzer); //在title和content中找word
多字段时默认是OR关系,要改变它,使用以下方法:
Query query = MultiFieldQueryParser.parse(“word”,new String[]{“title”,”content”},new int[]{MultiFieldQueryParser.REQUIRED_FIELD,MultiFieldQueryParser.PROHIBITED_FIELD},analyzer);
其中:
REQUIRED_FIELD 表示该条件必须有
PROHIBITED_FIELD 表示必须不含
搜索多个索引文件MultiSearcher
1) 建立多个索引:使用不同的索引目录,实例化不同的IndexWriter
2) 建立多索引搜索器:
Searcher[] searchers = new SEARCHER[2];
Searchers[0] = new IndexSearcher(dir1); //搜索索引目录一
Searchers[1]= new IndexSearcher(dir2);//搜索索引目录二
Searcher searcher = new MultiSearcher(serarchers);
3) 开始查询:Hits hits = searcher.search(query);
复合查询(多种查询条件的综合查询)
Query query=MultiFieldQueryParser.parse("索引",new String[]{"title","content"},analyzer);
Query mquery=new WildcardQuery(new Term("sender","bluedavy*"));
TermQuery tquery=new TermQuery(new Term("name","jerry"));
BooleanQuery bquery=new BooleanQuery();
bquery.add(query,true,false);
bquery.add(mquery,true,false);
bquery.add(tquery,true,false);
Searcher searcher=new IndexSearcher(indexFilePath);
Hits hits=searcher.search(bquery);
for (int i = 0; i < hits.length(); i++) {
System.out.println(hits.doc(i).get("name"));
}
高级篇
(2) 将需要检索的数据转换位Document的Filed对象,然后将Document用IndexWriter添加倒索引的文件中
(3) 处理索引信息,关闭IndexWriter流
(4) 创建搜索的Query
(5) 给IndexSearcher
? Keyword字段是指不需要分析器解析但需要被编入索引并保存到索引中的部分。JavaSourceCodeIndexer类使用该字段来保存导入类的声明。
? UnIndexed字段是既不被分析也不被索引,但是要被逐字逐句的将其值保存到索引中。由于我们一般要存储文件的位置但又很少用文件名作为关键字来搜索,所以用该字段来索引Java文件名。
? UnStored字段和UnIndexed字段相反。该类型的Field要被分析并编入索引,但其值不会被保存到索引中。由于存储方法的全部源代码需要大量的空间。所以用UnStored字段来存储被索引的方法源代码。可以直接从Java源文件中取出方法的源代码,这样作可以控制我们的索引的大小。
? Text字段在索引过程中是要被分析、索引并保存的。类名是作为Text字段来保存。下表展示了JavaSourceCodeIndexer类使用Field字段的一般情况。
Lucene
|
传统表
|
说明
|
IndexWriter
|
table
|
|
Document
|
一条记录
|
|
Field
|
每个字段
|
分为可被索引的,可切分的,不可被切分的,不可被索引的几种组合类型
|
Hits
|
RecoreSet
|
结果集
|
|
属性
|
默认值
|
说明
|
mergeFactor
|
org.apache.lucene.mergeFactor
|
10
|
控制index的大小和频率,两个作用
1.一个段有多少document
2.多少个段合成一个大段
|
maxMergeDocs
|
org.apache.lucene.maxMergeDocs
|
Integer.MAX_VALUE
|
限制一个段中的document数目
|
minMergeDocs
|
org.apache.lucene.minMergeDocs
|
10
|
缓存在内存中的document数目,超过他以后会写入到磁盘
|
maxFieldLength
|
|
1000
|
一个Field中最大Term数目,超过部分忽略,不会index到field中,所以自然也就搜索不到
|
把maxMergeDocs设置小,可以强制让达到一定数量的document写为一个段,这样可以抵消部分mergeFactor的作用.
minMergeDocs相当于设置一个小的cache,第一个这个数目的document会留在内存里面,不写入磁盘。这些参数同样是没有最佳值的,必须根据实际情况一点点调整。
maxFieldLength可以在任何时刻设置,设置后,接下来的index的Field会按照新的length截取,之前已经index的部分不会改变。可以设置为Integer.MAX_VALUE
查询方式
|
说明
|
TermQuery
|
条件查询
例如:TermQuery tquery=new TermQuery(new Term("name","jerry"));
name:字段名
jerry:要搜索的字符串
|
MultiTermQuery
|
多个字段进行同一关键字的查询
Query query= null;
Query =MultiFieldQueryParser.parse("我",new String[]
![]() Searcher searcher=new IndexSearcher(indexFilePath);
Hits hits=searcher.search(query); |
BooleanQuery
|
例如:BooleanQuery bquery=new BooleanQuery();
![]() bquery.add(mquery,true,false); bquery.add(tquery,true,false); Searcher searcher=new IndexSearcher(indexFilePath); Hits hits=searcher.search(bquery); |
WildcardQuery
|
语义查询(通配符查询)
例:Query query= new WildcardQuery(new Term("sender","*davy*"));
|
PhraseQuery
|
短语查询
|
PrefixQuery
|
前缀查询
|
PhrasePrefixQuery
|
短语前缀查询
|
FuzzyQuery
|
模糊查询
|
RangeQuery
|
范围查询
|
SpanQuery
|
范围查询
|
IndexSearcher[] searchers = new IndexSearcher[2];
searchers[0] = new IndexSearcher(m_indexpath);
searchers[1] = new IndexSearcher(m_outindexpath);
MultiSearcher multiSearcher = new MultiSearcher(searchers);
(2)还有个进行多条件搜索 and 与 or 的操作————
用 MultiFieldQueryParser
建议重新封装
MultiFieldQueryParser.Parser(p[],d[],f[],analyer) 成or 与 and操作合一
或者
BooleanQuery m_BooleanQuery = new BooleanQuery();
Query query = QueryParser.Parse(m_SearchText, "INSTRUMENT_NAME", analyzer);
Query query2 = QueryParser.Parse(m_SearchText2, "INSTRUMENT_NAME2", analyzer);
m_BooleanQuery.Add(query, true, false);
m_BooleanQuery.Add(query2, true, false);

Searcher searcher=new IndexSearcher(indexFilePath);
Hits hits=searcher.search(query);
for (int i = 0; i < hits.length(); i++)

System.out.println(hits.doc(i).get("name"));
}
即上文所说的“字段”,它是Document的片段section。
类型
|
Analyzed
|
Indexed
|
Stored
|
说明
|
Field.Keyword(String,String/Date)
|
N
|
Y
|
Y
|
这个Field用来储存会直接用来检索的比如(编号,姓名,日期等)
|
Field.UnIndexed(String,String)
|
N
|
N
|
Y
|
不会用来检索的信息,但是检索后需要显示的,比如,硬件序列号,文档的url地址
|
Field.UnStored(String,String)
|
Y
|
Y
|
N
|
大段文本内容,会用来检索,但是检索后不需要从index中取内容,可以根据url去load真实的内容
|
Field.Text(String,String)
|
Y
|
Y
|
Y
|
检索,获取都需要的内容,直接放index中,不过这样会增大index
|
Field.Text(String,Reader)
|
Y
|
Y
|
N
|
如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.
|