浏览 3992 次
锁定老帖子 主题:lucene 漫谈--入门与介绍(5)
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-04-25
lucene的搜索相当强大,它提供了很多辅助查询类,每个类都继承自Query类,各自完成一种特殊的查询,你可以像搭积木一样将它们任意组合使用,完成一些复杂操作;另外lucene还提供了Sort类对结果进行排序,提供了Filter类对查询条件进行限制。你或许会不自觉地拿它跟SQL语句进行比较:“lucene能执行and、or、order by、where、like ‘%xx%’操作吗?”回答是:“当然没问题!” 7.1 各种各样的Query 下面我们看看lucene到底允许我们进行哪些查询操作: 7.1.1 TermQuery 首先介绍最基本的查询,如果你想执行一个这样的查询:“在content域中包含‘lucene’的document”,那么你可以用TermQuery: Term t = new Term("content", " lucene"); Query query = new TermQuery(t); 7.1.2 BooleanQuery 如果你想这么查询:“在content域中包含java或perl的document”,那么你可以建立两个TermQuery并把它们用BooleanQuery连接起来: TermQuery termQuery1 = new TermQuery(new Term("content", "java"); TermQuery termQuery 2 = new TermQuery(new Term("content", "perl"); BooleanQuery booleanQuery = new BooleanQuery(); booleanQuery.add(termQuery 1, BooleanClause.Occur.SHOULD); booleanQuery.add(termQuery 2, BooleanClause.Occur.SHOULD); 7.1.3 WildcardQuery 如果你想对某单词进行通配符查询,你可以用WildcardQuery,通配符包括’?’匹配一个任意字符和’*’匹配零个或多个任意字符,例如你搜索’use*’,你可能找到’useful’或者’useless’: Query query = new WildcardQuery(new Term("content", "use*"); 7.1.4 PhraseQuery 你可能对中日关系比较感兴趣,想查找‘中’和‘日’挨得比较近(5个字的距离内)的文章,超过这个距离的不予考虑,你可以: PhraseQuery query = new PhraseQuery(); query.setSlop(5); query.add(new Term("content ", “中”)); query.add(new Term(“content”, “日”)); 那么它可能搜到“中日合作……”、“中方和日方……”,但是搜不到“中国某高层领导说日本欠扁”。 7.1.5 PrefixQuery 如果你想搜以‘中’开头的词语,你可以用PrefixQuery: PrefixQuery query = new PrefixQuery(new Term("content ", "中"); 7.1.6 FuzzyQuery FuzzyQuery用来搜索相似的term,使用Levenshtein算法。假设你想搜索跟‘wuzza’相似的词语,你可以: Query query = new FuzzyQuery(new Term("content", "wuzza"); 你可能得到‘fuzzy’和‘wuzzy’。 7.1.7 RangeQuery 另一个常用的Query是RangeQuery,你也许想搜索时间域从20080425到20080429之间的document,你可以用RangeQuery: RangeQuery query = new RangeQuery(new Term(“time”, “20080425”), new Term(“time”, “20080429”), true); 最后的true表示用闭合区间。 7.2 QueryParser 看了这么多Query,你可能会问:“不会让我自己组合各种Query吧,太麻烦了!”当然不会,lucene提供了一种类似于SQL语句的查询语句,我们姑且叫它lucene语句,通过它,你可以把各种查询一句话搞定,lucene会自动把它们查分成小块交给相应Query执行。下面我们对应每种Query演示一下: TermQuery可以用“field:key”方式,例如“content:lucene”。 BooleanQuery中‘与’用‘+’,‘或’用‘ ’,例如“content:java contenterl”。 WildcardQuery仍然用‘?’和‘*’,例如“content:use*”。 PhraseQuery用‘~’,例如“content:"中日"~5”。 PrefixQuery用‘*’,例如“中*”。 FuzzyQuery用‘~’,例如“content: wuzza ~”。 RangeQuery用‘[]’或‘{}’,前者表示闭区间,后者表示开区间,例如“time:[20080425 TO 20080429]”,注意TO区分大小写。 你可以任意组合query string,完成复杂操作,例如“标题或正文包括lucene,并且时间在20080425到20080429之间的文章”可以表示为:“+ (title:lucene content:lucene) +time:[20080425 TO 20080429]”。代码如下: Directory dir = FSDirectory.getDirectory(PATH, false); IndexSearcher is = new IndexSearcher(dir); QueryParser parser = new QueryParser("content", new StandardAnalyzer()); Query query = parser.parse("+(title:lucene content:lucene) +time:[20080425 TO 20080429]"; Hits hits = is.search(query); for (int i = 0; i < hits.length(); i++) { Document doc = hits.doc(i); System.out.println(doc.get("title"); } is.close(); 首先我们创建一个在指定文件目录上的IndexSearcher。 然后创建一个使用StandardAnalyzer作为分析器的QueryParser,它默认搜索的域是content。 接着我们用QueryParser来parse查询字串,生成一个Query。 然后利用这个Query去查找结果,结果以Hits的形式返回。 这个Hits对象包含一个列表,我们挨个把它的内容显示出来。 7.3 Filter filter的作用就是限制只查询索引的某个子集,它的作用有点像SQL语句里的where,但又有区别,它不是正规查询的一部分,只是对数据源进行预处理,然后交给查询语句。注意它执行的是预处理,而不是对查询结果进行过滤,所以使用filter的代价是很大的,它可能会使一次查询耗时提高一百倍。 最常用的filter是RangeFilter和QueryFilter。RangeFilter是设定只搜索指定范围内的索引;QueryFilter是在上次查询的结果中搜索。 Filter的使用非常简单,你只需创建一个filter实例,然后把它传给searcher。继续上面的例子,查询“时间在20080425到20080429之间的文章”除了将限制写在query string中,你还可以写在RangeFilter中: Directory dir = FSDirectory.getDirectory(PATH, false); IndexSearcher is = new IndexSearcher(dir); QueryParser parser = new QueryParser("content", new StandardAnalyzer()); Query query = parser.parse("title:lucene content:lucene"; RangeFilter filter = new RangeFilter("time", "20080425", "20080429", true, true); Hits hits = is.search(query, filter); for (int i = 0; i < hits.length(); i++) { Document doc = hits.doc(i); System.out.println(doc.get("title"); } is.close(); 7.4 Sort 有时你想要一个排好序的结果集,就像SQL语句的“order by”,lucene能做到:通过Sort。 Sort sort = new Sort(“time”); //相当于SQL的“order by time” Sort sort = new Sort(“time”, true); // 相当于SQL的“order by time desc” 下面是一个完整的例子: Directory dir = FSDirectory.getDirectory(PATH, false); IndexSearcher is = new IndexSearcher(dir); QueryParser parser = new QueryParser("content", new StandardAnalyzer()); Query query = parser.parse("title:lucene content:lucene"; RangeFilter filter = new RangeFilter("time", "20080425", "20080429", true, true); Sort sort = new Sort(“time”); Hits hits = is.search(query, filter, sort); for (int i = 0; i < hits.length(); i++) { Document doc = hits.doc(i); System.out.println(doc.get("title"); } is.close(); 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |