下面列出了怎么用org.apache.lucene.search.BooleanQuery的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public void addQueryTerms(BooleanQuery query, AdvancedSearchParams params) {
try {
ZipscriptQueryParams queryParams = params.getExtensionData(ZipscriptQueryParams.ZIPSCRIPTQUERYPARAMS);
if (queryParams.getMinPresent() != null || queryParams.getMaxPresent() != null) {
Query presentQuery = NumericRangeQuery.newIntRange("present",
queryParams.getMinPresent(), queryParams.getMaxPresent(), true, true);
query.add(presentQuery, Occur.MUST);
}
if (queryParams.getMinMissing() != null || queryParams.getMaxMissing() != null) {
Query missingQuery = NumericRangeQuery.newIntRange("missing",
queryParams.getMinMissing(), queryParams.getMaxMissing(), true, true);
query.add(missingQuery, Occur.MUST);
}
if (queryParams.getMinPercent() != null || queryParams.getMaxPercent() != null) {
Query percentQuery = NumericRangeQuery.newIntRange("percent",
queryParams.getMinPercent(), queryParams.getMaxPercent(), true, true);
query.add(percentQuery, Occur.MUST);
}
} catch (KeyNotFoundException e) {
// No MP3 terms to include, return without amending query
}
}
private Query getBoostedQuery(Query mltquery) {
BooleanQuery boostedQuery = (BooleanQuery)mltquery;
if (boostFields.size() > 0) {
BooleanQuery.Builder newQ = new BooleanQuery.Builder();
newQ.setMinimumNumberShouldMatch(boostedQuery.getMinimumNumberShouldMatch());
for (BooleanClause clause : boostedQuery) {
Query q = clause.getQuery();
float originalBoost = 1f;
if (q instanceof BoostQuery) {
BoostQuery bq = (BoostQuery) q;
q = bq.getQuery();
originalBoost = bq.getBoost();
}
Float fieldBoost = boostFields.get(((TermQuery) q).getTerm().field());
q = ((fieldBoost != null) ? new BoostQuery(q, fieldBoost * originalBoost) : clause.getQuery());
newQ.add(q, clause.getOccur());
}
boostedQuery = newQ.build();
}
return boostedQuery;
}
/**
* @param fieldName
* @param gramSize
* @return
* @throws TooGeneralQueryException
*/
public Query asNGramQuery(String fieldName, int gramSize) throws TooGeneralQueryException {
BooleanQuery.Builder orQueryBuilder = new BooleanQuery.Builder();
for (List<LeafLiterals> row: rows) {
BooleanQuery.Builder andQueryBuilder = new BooleanQuery.Builder();
for (LeafLiterals literals: row) {
if (literals.getLiteral() != null && literals.getLiteral().length()>=NGRAM_SIZE)
andQueryBuilder.add(new NGramLuceneQuery(fieldName, literals.getLiteral(), gramSize), Occur.MUST);
}
BooleanQuery andQuery = andQueryBuilder.build();
if (andQuery.clauses().size() != 0)
orQueryBuilder.add(andQuery, Occur.SHOULD);
}
BooleanQuery orQuery = orQueryBuilder.build();
if (orQuery.clauses().size() != 0)
return orQuery;
else
throw new TooGeneralQueryException();
}
public void testWildcardCombinations() throws Exception {
final BooleanQuery bq = new BooleanQuery.Builder()
.add(new TermQuery(new Term(FIELD, "term1")), BooleanClause.Occur.MUST)
.add(new PrefixQuery(new Term(FIELD, "term2")), BooleanClause.Occur.MUST)
.add(new TermQuery(new Term(FIELD, "term3")), BooleanClause.Occur.MUST_NOT)
.build();
try (Monitor monitor = newMonitor()) {
monitor.register(new MonitorQuery("1", bq));
MatchingQueries<HighlightsMatch> matches = monitor.match(buildDoc("term1 term22 term4"), HighlightsMatch.MATCHER);
HighlightsMatch m = matches.matches("1");
assertNotNull(m);
assertEquals(2, m.getHitCount());
}
}
void saveTerms( Collection<Query> flatQueries, IndexReader reader ) throws IOException{
for( Query query : flatQueries ){
while (query instanceof BoostQuery) {
query = ((BoostQuery) query).getQuery();
}
Set<String> termSet = getTermSet( query );
if( query instanceof TermQuery )
termSet.add( ((TermQuery)query).getTerm().text() );
else if( query instanceof PhraseQuery ){
for( Term term : ((PhraseQuery)query).getTerms() )
termSet.add( term.text() );
}
else if (query instanceof MultiTermQuery && reader != null) {
BooleanQuery mtqTerms = (BooleanQuery) query.rewrite(reader);
for (BooleanClause clause : mtqTerms) {
termSet.add (((TermQuery) clause.getQuery()).getTerm().text());
}
}
else
throw new RuntimeException( "query \"" + query.toString() + "\" must be flatten first." );
}
}
public DocListAndSet getMoreLikeThis( int id, int start, int rows, List<Query> filters, List<InterestingTerm> terms, int flags ) throws IOException
{
Document doc = reader.document(id);
rawMLTQuery = mlt.like(id);
boostedMLTQuery = getBoostedQuery( rawMLTQuery );
if( terms != null ) {
fillInterestingTermsFromMLTQuery( boostedMLTQuery, terms );
}
// exclude current document from results
BooleanQuery.Builder realMLTQuery = new BooleanQuery.Builder();
realMLTQuery.add(boostedMLTQuery, BooleanClause.Occur.MUST);
realMLTQuery.add(
new TermQuery(new Term(uniqueKeyField.getName(), uniqueKeyField.getType().storedToIndexed(doc.getField(uniqueKeyField.getName())))),
BooleanClause.Occur.MUST_NOT);
this.realMLTQuery = realMLTQuery.build();
DocListAndSet results = new DocListAndSet();
if (this.needDocSet) {
results = searcher.getDocListAndSet(this.realMLTQuery, filters, null, start, rows, flags);
} else {
results.docList = searcher.getDocList(this.realMLTQuery, filters, null, start, rows, flags);
}
return results;
}
@Override
public Query applyMinimumShouldMatch(final BooleanQuery query) {
final List<BooleanClause> clauses = query.clauses();
if (clauses.size() < 2) {
return query;
}
for (final BooleanClause clause : clauses) {
if ((clause.getQuery() instanceof BooleanQuery) && (clause.getOccur() != BooleanClause.Occur.MUST)) {
return query; // seems to be a complex query with sub queries - do not
// apply mm
}
}
return SolrPluginUtils.setMinShouldMatch(query, minShouldMatch);
}
public void testWithSameTermQuery() throws IOException {
indexWriter.addDocument(newDoc("Yin yang, yin gap yang"));
initReaderSearcherHighlighter();
BooleanQuery query = new BooleanQuery.Builder()
.add(new TermQuery(new Term("body", "yin")), BooleanClause.Occur.MUST)
.add(newPhraseQuery("body", "yin yang"), BooleanClause.Occur.MUST)
// add queries for other fields; we shouldn't highlight these because of that.
.add(new TermQuery(new Term("title", "yang")), BooleanClause.Occur.SHOULD)
.build();
TopDocs topDocs = searcher.search(query, 10, Sort.INDEXORDER);
dupMatchAllowed.set(false); // We don't want duplicates from "Yin" being in TermQuery & PhraseQuery.
String[] snippets = highlighter.highlight("body", query, topDocs);
if (highlighter.getFlags("body").contains(HighlightFlag.WEIGHT_MATCHES)) {
assertArrayEquals(new String[]{"<b>Yin yang</b>, <b>yin</b> gap yang"}, snippets);
} else {
assertArrayEquals(new String[]{"<b>Yin</b> <b>yang</b>, <b>yin</b> gap yang"}, snippets);
}
}
private Query toBooleanQuery(SearchQuery.Boolean booleanQuery) {
final BooleanQuery.Builder builder = new BooleanQuery.Builder();
final BooleanClause.Occur occur;
switch(booleanQuery.getOp()) {
case AND:
occur = BooleanClause.Occur.MUST;
break;
case OR:
occur = BooleanClause.Occur.SHOULD;
break;
default:
throw new AssertionError("Unknown boolean operator: " + booleanQuery.getOp());
}
for(SearchQuery clause: booleanQuery.getClausesList()) {
builder.add(toLuceneQuery(clause), occur);
}
return builder.build();
}
public void testEnableGraphQueries() throws Exception {
QueryParser dumb = new QueryParser("field", new Analyzer1());
dumb.setSplitOnWhitespace(false);
dumb.setEnableGraphQueries(false);
TermQuery pig = new TermQuery(new Term("field", "pig"));
// A multi-word synonym source will just form a boolean query when graph queries are disabled:
Query inner = new SynonymQuery.Builder("field")
.addTerm(new Term("field", "cavy"))
.addTerm(new Term("field", "guinea"))
.build();
BooleanQuery.Builder b = new BooleanQuery.Builder();
b.add(inner, BooleanClause.Occur.SHOULD);
b.add(pig, BooleanClause.Occur.SHOULD);
BooleanQuery query = b.build();
assertEquals(query, dumb.parse("guinea pig"));
}
private void update(MailboxId mailboxId, MessageUid uid, Flags f) throws IOException {
try (IndexSearcher searcher = new IndexSearcher(IndexReader.open(writer, true))) {
BooleanQuery query = new BooleanQuery();
query.add(new TermQuery(new Term(MAILBOX_ID_FIELD, mailboxId.serialize())), BooleanClause.Occur.MUST);
query.add(createQuery(MessageRange.one(uid)), BooleanClause.Occur.MUST);
query.add(new PrefixQuery(new Term(FLAGS_FIELD, "")), BooleanClause.Occur.MUST);
TopDocs docs = searcher.search(query, 100000);
ScoreDoc[] sDocs = docs.scoreDocs;
for (ScoreDoc sDoc : sDocs) {
Document doc = searcher.doc(sDoc.doc);
doc.removeFields(FLAGS_FIELD);
indexFlags(doc, f);
writer.updateDocument(new Term(ID_FIELD, doc.get(ID_FIELD)), doc);
}
}
}
@Test
public void test5() throws ParseException, IOException {
parser = new SuperParser(LUCENE_VERSION, getFieldManager(new WhitespaceAnalyzer(LUCENE_VERSION)), true, null,
ScoreType.SUPER, new Term("_primedoc_"));
Query query = parser.parse("<a.a:a a.d:{e TO f} a.b:b a.test:hello\\<> -<g.c:c g.d:d>");
BooleanQuery booleanQuery1 = new BooleanQuery();
booleanQuery1.add(new TermQuery(new Term("a.a", "a")), Occur.SHOULD);
booleanQuery1.add(new TermRangeQuery("a.d", new BytesRef("e"), new BytesRef("f"), false, false), Occur.SHOULD);
booleanQuery1.add(new TermQuery(new Term("a.b", "b")), Occur.SHOULD);
// std analyzer took the "<" out
booleanQuery1.add(new TermQuery(new Term("a.test", "hello<")), Occur.SHOULD);
BooleanQuery booleanQuery2 = new BooleanQuery();
booleanQuery2.add(new TermQuery(new Term("g.c", "c")), Occur.SHOULD);
booleanQuery2.add(new TermQuery(new Term("g.d", "d")), Occur.SHOULD);
SuperQuery superQuery1 = new SuperQuery(booleanQuery1, ScoreType.SUPER, new Term("_primedoc_"));
SuperQuery superQuery2 = new SuperQuery(booleanQuery2, ScoreType.SUPER, new Term("_primedoc_"));
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(superQuery1, Occur.SHOULD);
booleanQuery.add(superQuery2, Occur.MUST_NOT);
assertQuery(booleanQuery, query);
}
public Query combineGrouped(List<Query> queries) {
if (queries == null || queries.isEmpty()) {
return null;
}
if (queries.size() == 1) {
return queries.get(0);
}
if (groupDismax) {
return new DisjunctionMaxQuery(queries, tieBreaker);
} else {
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
for (Query query : queries) {
booleanQuery.add(query, BooleanClause.Occur.SHOULD);
}
return booleanQuery.build();
}
}
private void queryBasedPercolating(Engine.Searcher percolatorSearcher, PercolateContext context, QueryCollector percolateCollector) throws IOException {
Query percolatorTypeFilter = context.indexService().mapperService().documentMapper(TYPE_NAME).typeFilter();
final Query filter;
if (context.aliasFilter() != null) {
BooleanQuery.Builder booleanFilter = new BooleanQuery.Builder();
booleanFilter.add(context.aliasFilter(), BooleanClause.Occur.MUST);
booleanFilter.add(percolatorTypeFilter, BooleanClause.Occur.MUST);
filter = booleanFilter.build();
} else {
filter = percolatorTypeFilter;
}
Query query = Queries.filtered(context.percolateQuery(), filter);
percolatorSearcher.searcher().search(query, percolateCollector);
percolateCollector.aggregatorCollector.postCollection();
if (context.aggregations() != null) {
aggregationPhase.execute(context);
}
}
public void testScoreModifyingSource() throws Exception {
BooleanQuery bq = new BooleanQuery.Builder()
.add(new TermQuery(new Term(TEXT_FIELD, "first")), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term(TEXT_FIELD, "text")), BooleanClause.Occur.SHOULD)
.build();
TopDocs plain = searcher.search(bq, 1);
FunctionScoreQuery fq = FunctionScoreQuery.boostByValue(bq, DoubleValuesSource.fromIntField("iii"));
QueryUtils.check(random(), fq, searcher, rarely());
int[] expectedDocs = new int[]{ 4, 7, 9, 8, 12 };
TopDocs docs = searcher.search(fq, 5);
assertEquals(plain.totalHits.value, docs.totalHits.value);
for (int i = 0; i < expectedDocs.length; i++) {
assertEquals(expectedDocs[i], docs.scoreDocs[i].doc);
}
Explanation expl = searcher.explain(fq, 4);
assertTrue(expl.toString().contains("first"));
assertTrue(expl.toString().contains("iii"));
}
private void innerDelete(DeleteByQuery delete) throws EngineException {
try {
Query query = delete.query();
if (delete.aliasFilter() != null) {
query = new BooleanQuery.Builder()
.add(query, Occur.MUST)
.add(delete.aliasFilter(), Occur.FILTER)
.build();
}
if (delete.nested()) {
query = new IncludeNestedDocsQuery(query, delete.parentFilter());
}
indexWriter.deleteDocuments(query);
translog.add(new Translog.DeleteByQuery(delete));
} catch (Throwable t) {
maybeFailEngine("delete_by_query", t);
throw new DeleteByQueryFailedEngineException(shardId, delete, t);
}
// TODO: This is heavy, since we refresh, but we must do this because we don't know which documents were in fact deleted (i.e., our
// versionMap isn't updated), so we must force a cutover to a new reader to "see" the deletions:
refresh("delete_by_query");
}
private BooleanQuery buildLineageQuery(final Collection<String> flowFileUuids) {
// Create a query for all Events related to the FlowFiles of interest. We do this by adding all ID's as
// "SHOULD" clauses and then setting the minimum required to 1.
final BooleanQuery lineageQuery;
if (flowFileUuids == null || flowFileUuids.isEmpty()) {
lineageQuery = null;
} else {
final BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
for (final String flowFileUuid : flowFileUuids) {
final TermQuery termQuery = new TermQuery(new Term(SearchableFields.FlowFileUUID.getSearchableFieldName(), flowFileUuid));
queryBuilder.add(new BooleanClause(termQuery, BooleanClause.Occur.SHOULD));
}
lineageQuery = queryBuilder.build();
}
return lineageQuery;
}
/**
* Creates graph phrase query from the tokenstream contents
*/
protected Query analyzeGraphPhrase(TokenStream source, String field, int phraseSlop)
throws IOException {
source.reset();
GraphTokenStreamFiniteStrings graph = new GraphTokenStreamFiniteStrings(source);
// Creates a boolean query from the graph token stream by extracting all the
// finite strings from the graph and using them to create phrase queries with
// the appropriate slop.
BooleanQuery.Builder builder = new BooleanQuery.Builder();
Iterator<TokenStream> it = graph.getFiniteStrings();
while (it.hasNext()) {
Query query = createFieldQuery(it.next(), BooleanClause.Occur.MUST, field, true, phraseSlop);
if (query != null) {
builder.add(query, BooleanClause.Occur.SHOULD);
}
}
return builder.build();
}
@Override
public Query build() {
Map<String, BytesRef[]> collectedTerms = new HashMap<>();
for (Map.Entry<String, BytesRefHash> entry : terms.entrySet()) {
collectedTerms.put(entry.getKey(), convertHash(entry.getValue()));
}
BooleanQuery.Builder parent = new BooleanQuery.Builder();
for (int i = 0; i < passes; i++) {
BooleanQuery.Builder child = new BooleanQuery.Builder();
for (String field : terms.keySet()) {
child.add(new TermInSetQuery(field(field, i), collectedTerms.get(field)), BooleanClause.Occur.SHOULD);
}
parent.add(child.build(), BooleanClause.Occur.MUST);
}
return parent.build();
}
@Test
public void testExtractTwoSubqueryFields() {
Query q1 = new TermQuery(new Term("field1", "value1"));
Query q2 = new TermQuery(new Term("field2", "value2"));
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(new BooleanClause(q1, BooleanClause.Occur.MUST));
builder.add(new BooleanClause(q2, BooleanClause.Occur.MUST));
BooleanQuery booleanQuery = builder.build();
BooleanQueryExtractor booleanQueryExtractor = new BooleanQueryExtractor();
Set<String> extractedFieldNames = new HashSet<>();
booleanQueryExtractor.extractSubQueriesFields(booleanQuery, DEFAULT_EXTRACTORS, extractedFieldNames);
assertEquals(2, extractedFieldNames.size());
assertTrue(extractedFieldNames.contains("field1"));
assertTrue(extractedFieldNames.contains("field2"));
}
public List<String> query(String question_text) {
List<String> results = new ArrayList<>();
try {
BooleanQuery q = new BooleanQuery();
for (String word : question_text.split("\\W+")) {
q.add(new TermQuery(new Term("text", word)), BooleanClause.Occur.SHOULD);
q.add(new TermQuery(new Term("text", word.toLowerCase())), BooleanClause.Occur.SHOULD);
}
TopDocs topDocs = searcher.search(q, 1);
ScoreDoc[] hits = topDocs.scoreDocs;
// This isn't range based because we need the rank
for (int i=0; i < hits.length; i++) {
ScoreDoc s = hits[i];
Document doc = searcher.doc(s.doc);
results.add(doc.get("uri"));
}
} catch (IOException e) {
System.out.println("Failed to query Lucene. Is the index in the correct location?");
e.printStackTrace();
}
return results;
}
public static BooleanQuery setMinShouldMatch(BooleanQuery q, String spec, boolean mmAutoRelax) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
for (BooleanClause clause : q) {
builder.add(clause);
}
setMinShouldMatch(builder, spec, mmAutoRelax);
return builder.build();
}
private Query combineQueries(Query q1, Query q2) {
if (q1 == null) {
return q2;
} else if (q2 == null) {
return q1;
} else {
BooleanQuery combinedQry = new BooleanQuery();
combinedQry.add(q1, BooleanClause.Occur.MUST);
combinedQry.add(q2, BooleanClause.Occur.MUST);
return combinedQry;
}
}
public void testTopLevelBoost() throws Exception {
Query q = new TermQuery(new Term(FIELD, "w1"));
FunctionScoreQuery csq = new FunctionScoreQuery(q, DoubleValuesSource.constant(5));
BooleanQuery.Builder bqB = new BooleanQuery.Builder();
bqB.add(new MatchAllDocsQuery(), BooleanClause.Occur.MUST);
bqB.add(csq, BooleanClause.Occur.MUST);
BooleanQuery bq = bqB.build();
qtest(new BoostQuery(bq, 6), new int[] { 0,1,2,3 });
}
public void testQuery() {
DisjunctionMaxQuery dismax = new DisjunctionMaxQuery(
Arrays.asList(new TermQuery(new Term("foo1", "bar1")), new TermQuery(new Term("baz1", "bam1"))), 1.0f);
BooleanQuery bq = new BooleanQuery.Builder()
.add(new TermQuery(new Term("foo2", "bar2")), BooleanClause.Occur.SHOULD)
.add(new PhraseQuery.Builder().add(new Term("foo3", "baz3")).build(), BooleanClause.Occur.MUST_NOT)
.add(dismax, BooleanClause.Occur.MUST)
.build();
long actual = sizeOf(bq);
long estimated = RamUsageEstimator.sizeOfObject(bq);
// sizeOfObject uses much lower default size estimate than we normally use
// but the query-specific default is so large that the comparison becomes meaningless.
assertEquals((double)actual, (double)estimated, (double)actual * 0.5);
}
public void testDisableSlop() {
PhraseQuery expectedPhrase = new PhraseQuery("field", "foo", "bar");
BooleanQuery.Builder expected = new BooleanQuery.Builder();
expected.add(expectedPhrase, Occur.MUST);
expected.add(new TermQuery(new Term("field", "~2")), Occur.MUST);
assertEquals(expected.build(), parse("\"foo bar\"~2", ~NEAR_OPERATOR));
}
private static Query fixSuperQuery(Query query, String name, String fieldLessFieldName) {
if (query instanceof BooleanQuery) {
BooleanQuery bq = (BooleanQuery) query;
BooleanQuery newBq = new BooleanQuery();
for (BooleanClause booleanClause : bq) {
newBq.add(fixSuperQuery(booleanClause.getQuery(), name, fieldLessFieldName), booleanClause.getOccur());
}
return newBq;
} else if (query instanceof SuperQuery) {
SuperQuery sq = (SuperQuery) query;
return setFieldIfNeeded(sq.getQuery(), name, fieldLessFieldName);
} else {
return setFieldIfNeeded(query, name, fieldLessFieldName);
}
}
public void test2SubInfos() throws Exception {
BooleanQuery.Builder query = new BooleanQuery.Builder();
query.add( pqF( "the", "both" ), Occur.MUST );
query.add( tq( "examples" ), Occur.MUST );
testCase( query.build(), 1000,
"subInfos=(examples((19,27))examples((66,74))theboth((195,203)))/1.8411169(0,1000)",
1.8411169 );
}
public void testTopLevelSort() throws IOException {
Shard shard = new Shard();
indexRandomDocs(shard.writer);
IndexSearcher searcher = shard.getIndexSearcher();
Sort sort = new Sort(new SortField("length", SortField.Type.LONG));
Query blockEndQuery = new TermQuery(new Term("blockEnd", "true"));
GroupingSearch grouper = new GroupingSearch(blockEndQuery);
grouper.setGroupDocsLimit(10);
grouper.setGroupSort(sort); // groups returned sorted by length, chapters within group sorted by relevancy
Query topLevel = new TermQuery(new Term("text", "grandmother"));
TopGroups<?> tg = grouper.search(searcher, topLevel, 0, 5);
// The sort value of the top doc in the top group should be the same as the sort value
// of the top result from the same search done with no grouping
TopDocs topDoc = searcher.search(topLevel, 1, sort);
assertEquals(((FieldDoc)topDoc.scoreDocs[0]).fields[0], tg.groups[0].groupSortValues[0]);
for (int i = 0; i < tg.groups.length; i++) {
String bookName = searcher.doc(tg.groups[i].scoreDocs[0].doc).get("book");
// The contents of each group should be equal to the results of a search for
// that group alone, sorted by score
Query filtered = new BooleanQuery.Builder()
.add(topLevel, BooleanClause.Occur.MUST)
.add(new TermQuery(new Term("book", bookName)), BooleanClause.Occur.FILTER)
.build();
TopDocs td = searcher.search(filtered, 10);
assertScoreDocsEquals(td.scoreDocs, tg.groups[i].scoreDocs);
if (i > 1) {
assertSortsBefore(tg.groups[i - 1], tg.groups[i]);
}
}
shard.close();
}
@Test
public void testSimpleSuperQuery() throws CorruptIndexException, IOException, InterruptedException {
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(wrapSuper(new TermQuery(new Term(PERSON_NAME, NAME1))), Occur.MUST);
booleanQuery.add(wrapSuper(new TermQuery(new Term(ADDRESS_STREET, STREET1))), Occur.MUST);
Directory directory = createIndex();
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
TopDocs topDocs = searcher.search(booleanQuery, 10);
assertEquals(2, topDocs.totalHits);
assertEquals("1", searcher.doc(topDocs.scoreDocs[0].doc).get(ROW_ID));
assertEquals("3", searcher.doc(topDocs.scoreDocs[1].doc).get(ROW_ID));
}