1、搜索处理示例
public class Searcher {
public static void search(String indexDir, String q) throws IOException, ParseException {
// 得到读取索引文件的路径
Directory dir = FSDirectory.open(Paths.get(indexDir));
// 通过Dir得到路径下所有文件
IndexReader reader = DirectoryReader.open(dir);
// 建立索引查询器
IndexSearcher searcher = new IndexSearcher(reader);
// 实例化分析器
Analyzer analyzer = new StandardAnalyzer();
/********建立查询解析器********/
// 第一个参数是要查询的字段; 第二个参数市分析器Analyzer
String[] fields = {"name", "path"};
Map fieldMap = new HashMap<>();
fieldMap.put("name",100.0f);
fieldMap.put("path",1.0f);
QueryParser parser = new MultiFieldQueryParser(fields,new CJKAnalyzer());
// 根据传进来的q查找
Query query = parser.parse(q);
// 计算索引开始时间
long start = System.currentTimeMillis();
/********开始查询********/
// 第一个参数是通过传过来的参数来查找得到的query; 第二个参数是要查询出的行数
TopDocs hits = searcher.search(query,10);
// 计算索引结束时间
long end = System.currentTimeMillis();
System.out.println("匹配 "+ q + ",查询到 " + hits.totalHits + " 个记录, 用时:" + (end - start));
// 遍历hits.scoreDocs,得到scoreDoc
// scoreDoc:得分文档,即得到的文档 scoreDocs:代表topDocs这个文档数组
for (ScoreDoc scoreDoc : hits.scoreDocs) {
Document doc = searcher.doc(scoreDoc.doc);
System.out.println("name:" + doc.get("name") + " ,path=" + doc.get("path"));
}
//关闭reader
reader.close();
}
}
2、搜索类型
在lucene中,查询就是构建Query对象。搜索文档时会实例化一个IndexSearcher对象,IndexSearcher对象的search()方法完成搜索过程,Query对象作为search()方法的对象。搜索结果会保存在一个TopDoc类型的文档集合中,遍历TopDocs集合输出文档信息。
2.1、多域搜索(MultiFieldQueryParser)
MultiFieldQueryParser可以查询多个字段。示例如下:
String[] fields = {"title","content"};
Analyzer analyzer = new IKAnalyzer6X(true);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,analyzer);
Query q = parser.parse("日本");
2.2、词项搜索(TermQuery)
TermQuery是最简单也是最常用的Query。在搜索引擎中最基本的搜索就是在索引中搜索某一词条,而TermQuery就是用来完成这项工作的。示例代码:
Term term = new Term("title","美国");
Query q = new TermQuery(term);
2.3、布尔搜索(BooleanQuery)
BooleanQuery是常用的查询,其实际是一个组合查询,在使用时可以把各种Query对象添加进去并标明他们之间的逻辑关系。BooleanQuery本身是一个布尔子句的容积,其专门提供了api方法想其中添加子句,并标明他们之间的关系。代码示例:
Query q1 = new TermQuery(new Term("title","中国"));
Query q2 = new TermQuery(new Term("content","北京"));
BooleanClause bc1 = new BooleanClause(q1, Occur.MUST);
BooleanClause bc2 = new BooleanClause(q2, Occur.MUST_NOT);
BooleanQuery bq = new BooleanQuery.Builder().add(bc1).add(bc2).build();
2.4、范围搜索(RangeQuery )
RangeQuery可以查询满足一定范围的文档,如某段时间的所有文档等。RangeQuery表示在某范围内查询的条件,实现从一个开始词条到一个结束词条的搜索功能。示例如下:
Query rq = IntPoint.newRangeQuery("relay",1000,2000);
2.5、前缀搜索(PrefixQuery)
PrefixQuery就是使用前缀来进行查找的。通常先定义一个词条Term。该词条包含查找的字段名及关键字前缀,然后通过该词条构造一个PrefixQuery对象,就可以进行前缀查询了。示例如下:
Term t = new Term("title","你好");
Query pq = new PrefixQuery(term);
2.6、多关键字搜索(PhraseQuery)
用户搜索时,可能会输入几个不同的关键词,这些关键词要么紧密相连,构成一个精确的短语,要么直接插入其他无关内容。而hraseQuery正可以满足多关键词的查询,其通过add()方法可以向用户添加多个关键字,同时还可通过setSlop()设定坡度变量来确定是否允许或允许多少无关的词汇存在。示例代码:
PhraseQuery.Builder builder = new PhraseQuery.Builder();
builder.add(new Term("title","中国"),2);
builder.add(new Term("title","美国"),3);
PhraseQuery pq = builder.build();
2.7、模糊搜索(FuzzyQuery)
FuzzyQuery是一种模糊搜索,其可以简单识别两个相近的词语。如将“Trump”拼写错误为“tramp”,使用FuzzyQuery可以得到正确的结果。示例如下:
Term t = new Term("title","tramp");
FuzzyQuery fq = new FuzzyQuery(t);
2.8、通配符搜索(WildcardQuery)
WildcardQuery为通配符查询,代码示例:
WildcardQuery wq = new WildcardQuery(new Term("title","学?"));
3、搜索过滤
过滤器是用于缩小搜索空间的一种机制,它把可能的搜索匹配结果仅限制在所有文档的一个子集中。他们可以用来对得到的搜索匹配结果进行进一步的搜索,以实现在搜索结果中继续搜索的特性。此外,它们还可以用来限制文档的搜索空间。安全过滤允许用户只能看到属于自己的文档搜索结果,即时这些查询实际上还是匹配上了其他文档。
TermRangeFilter:只对包含特定项范围的文档进行匹配操作。功能与TermRangeQuery一致,但没有评分操作。TermRangeFilter的处理对象是文本域,如果为数字,需使用NumericRangeFilter。
NumericRangeFilter:复制过滤数值范围的文档。其功能与去除评分功能的NumericRangeQuery类一致;
FieldCacheRangeFilter:提供了另一种范围的过滤选择。它所完成的过滤功能同TermRangeFilter和NumericRangeFilter加起来一样,但它使用的却是基于lucene的域缓存机制。其可以在某些情况下带来系统性能提升。
QueryWrapperFilter:使用查询中匹配的文档来对随后搜索中可以访问的文档进行限制。它允许你将带有评分功能的查询转换为不带评分功能的过滤器。使用QueryWrapperFilter可以将被搜索文档限制在特定的类别范围内。
SpanQueryFilter:SpanQueryFilter完成与QueryWrapperFilter一样的功能,区别是前者能够保留针对每个匹配文档的跨度。
PerfixFilter:其是PrefixQuery的必然结果,它会对包含以特定前缀开始的项的文档进行匹配。我们可以用PrefixFilter来讲搜索范围限制在某个指定类别的所有书籍中。