BooleanQuery也是实际开发过程中经常使用的一种Query。它其实是一个组合的Query,在使用时可以把各种Query对象添加进去并标明它们之间的逻辑关系。
BooleanQuery本身来讲是一个布尔子句的容器,它提供了专门的API方法往其中添加子句,并标明它们之间的关系,以下代码为BooleanQuery提供的用于添加子句的API接口:
public void add(Query query, boolean required, boolean prohibited);
注意:BooleanQuery是可以嵌套的,一个BooleanQuery可以成为另一个BooleanQuery的条件子句。
package ch11; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; public class BooleanQueryTest1 { public static void main(String[] args) throws Exception { // 生成新的Document对象 Document doc1 = new Document(); doc1.add(Field.Text("name", "word1 word2 word3")); doc1.add(Field.Keyword("title", "doc1")); Document doc2 = new Document(); doc2.add(Field.Text("name", "word1 word4 word5")); doc2.add(Field.Keyword("title", "doc2")); Document doc3 = new Document(); doc3.add(Field.Text("name", "word1 word2 word6")); doc3.add(Field.Keyword("title", "doc3")); // 生成索引书写器 IndexWriter writer = new IndexWriter("c://index", new StandardAnalyzer(), true); // 添加到索引中 writer.addDocument(doc1); writer.addDocument(doc2); writer.addDocument(doc3); writer.close(); Query query1 = null; Query query2 = null; BooleanQuery query = null; Hits hits = null; // 生成IndexSearcher对象 IndexSearcher searcher = new IndexSearcher("c://index"); query1 = new TermQuery(new Term("name", "word1")); query2 = new TermQuery(new Term("name", "word2")); // 构造一个布尔查询 query = new BooleanQuery(); // 添加两个子查询 query.add(query1, true, false); query.add(query2, true, false); hits = searcher.search(query); printResult(hits, "word1和word2"); } public static void printResult(Hits hits, String key) throws Exception { System.out.println("查找 /"" + key + "/" :"); if (hits != null) { if (hits.length() == 0) { System.out.println("没有找到任何结果"); } else { System.out.println("找到" + hits.length() + "个结果"); for (int i = 0; i < hits.length(); i++) { Document d = hits.doc(i); String dname = d.get("title"); System.out.print(dname + " "); } System.out.println(); System.out.println(); } } } }
代码首先构造了两个TermQuery,然后构造了一个BooleanQuery的对象,并将两个TermQuery当成它的查询子句加入Boolean查询中。
再来看一下BooleanQuery的add方法,除了它的第一个参数外,它还有另外两个布尔型的参数。第1个参数的意思是当前所加入的查询子句是否必须满足,第2个参数的意思是当前所加入的查询子句是否不需要满足。这样,当这两个参数分别选择true和false时,会有4种不同的组合。
true &false:表明当前加入的子句是必须要满足的。 false&true:表明当前加入的子句是不可以被满足的。 false&false:表明当前加入的子句是可选的。 true&true:错误的情况。
由前面的示例可以看出由于加入的两个子句都选用了true&false的组合,因此它们两个都是需要被满足的,也就构成了实际上的“与”关系
如果是要进行“或”运算,则可按如下代码来构建查询子句
query.add(query1, false, false); query.add(query2, false, false);
由于布尔型的查询是可以嵌套的,因此可以表示多种条件下的组合。不过,如果子句的数目太多,可能会导致查找效率的降低。因此,Lucene给出了一个默认的限制,就是布尔型Query的子句数目不能超过1024。