public void testDefaultMinShouldMatch() throws Exception { // Queries have a minShouldMatch of 0 BooleanQuery bq = (BooleanQuery) parseQuery(boolQuery().must(termQuery("foo", "bar")).buildAsBytes()) .toQuery(createShardContext()); assertEquals(0, bq.getMinimumNumberShouldMatch()); bq = (BooleanQuery) parseQuery(boolQuery().should(termQuery("foo", "bar")).buildAsBytes()) .toQuery(createShardContext()); assertEquals(0, bq.getMinimumNumberShouldMatch()); // Filters have a minShouldMatch of 0/1 ConstantScoreQuery csq = (ConstantScoreQuery) parseQuery(constantScoreQuery(boolQuery().must(termQuery("foo", "bar"))).buildAsBytes()) .toQuery(createShardContext()); bq = (BooleanQuery) csq.getQuery(); assertEquals(0, bq.getMinimumNumberShouldMatch()); csq = (ConstantScoreQuery) parseQuery( constantScoreQuery(boolQuery().should(termQuery("foo", "bar"))).buildAsBytes()) .toQuery(createShardContext()); bq = (BooleanQuery) csq.getQuery(); assertEquals(1, bq.getMinimumNumberShouldMatch()); }
public void testMinShouldMatchFilterWithoutShouldClauses() throws Exception { BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder.filter(new BoolQueryBuilder().must(new MatchAllQueryBuilder())); Query query = boolQueryBuilder.toQuery(createShardContext()); assertThat(query, instanceOf(BooleanQuery.class)); BooleanQuery booleanQuery = (BooleanQuery) query; assertThat(booleanQuery.getMinimumNumberShouldMatch(), equalTo(0)); assertThat(booleanQuery.clauses().size(), equalTo(1)); BooleanClause booleanClause = booleanQuery.clauses().get(0); assertThat(booleanClause.getOccur(), equalTo(BooleanClause.Occur.FILTER)); assertThat(booleanClause.getQuery(), instanceOf(BooleanQuery.class)); BooleanQuery innerBooleanQuery = (BooleanQuery) booleanClause.getQuery(); // we didn't set minimum should match initially, there are no should clauses so it should be 0 assertThat(innerBooleanQuery.getMinimumNumberShouldMatch(), equalTo(0)); assertThat(innerBooleanQuery.clauses().size(), equalTo(1)); BooleanClause innerBooleanClause = innerBooleanQuery.clauses().get(0); assertThat(innerBooleanClause.getOccur(), equalTo(BooleanClause.Occur.MUST)); assertThat(innerBooleanClause.getQuery(), instanceOf(MatchAllDocsQuery.class)); }
@Override public void write(DataOutput out) throws IOException { out.writeBoolean(query.isCoordDisabled()); out.writeFloat(query.getBoost()); out.writeInt(query.getMinimumNumberShouldMatch()); BooleanClause[] clauses = query.getClauses(); out.writeInt(clauses.length); for (int i = 0; i < clauses.length; i++) { BooleanClauseWritable booleanClauseWritable = new BooleanClauseWritable(clauses[i]); booleanClauseWritable.write(out); } }
public void testToQueryBooleanQueryMultipleBoosts() throws Exception { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); int numBoosts = randomIntBetween(2, 10); float[] boosts = new float[numBoosts + 1]; String queryStringPrefix = ""; String queryStringSuffix = ""; for (int i = 0; i < boosts.length - 1; i++) { float boost = 2.0f / randomIntBetween(3, 20); boosts[i] = boost; queryStringPrefix += "("; queryStringSuffix += ")^" + boost; } String queryString = queryStringPrefix + "foo bar" + queryStringSuffix; float mainBoost = 2.0f / randomIntBetween(3, 20); boosts[boosts.length - 1] = mainBoost; QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(queryString) .field(STRING_FIELD_NAME) .minimumShouldMatch("2") .boost(mainBoost); Query query = queryStringQueryBuilder.toQuery(createShardContext()); for (int i = boosts.length - 1; i >= 0; i--) { assertThat(query, instanceOf(BoostQuery.class)); BoostQuery boostQuery = (BoostQuery) query; assertThat(boostQuery.getBoost(), equalTo(boosts[i])); query = boostQuery.getQuery(); } assertThat(query, instanceOf(BooleanQuery.class)); BooleanQuery booleanQuery = (BooleanQuery) query; assertThat(booleanQuery.getMinimumNumberShouldMatch(), equalTo(2)); assertThat(booleanQuery.clauses().get(0).getOccur(), equalTo(BooleanClause.Occur.SHOULD)); assertThat( booleanQuery.clauses().get(0).getQuery(), equalTo(new TermQuery(new Term(STRING_FIELD_NAME, "foo")))); assertThat(booleanQuery.clauses().get(1).getOccur(), equalTo(BooleanClause.Occur.SHOULD)); assertThat( booleanQuery.clauses().get(1).getQuery(), equalTo(new TermQuery(new Term(STRING_FIELD_NAME, "bar")))); }
/** @see #toString(Query,IndexSchema) */ public static void toString(Query query, IndexSchema schema, Appendable out, int flags) throws IOException { boolean writeBoost = true; if (query instanceof TermQuery) { TermQuery q = (TermQuery) query; Term t = q.getTerm(); FieldType ft = writeFieldName(t.field(), schema, out, flags); writeFieldVal(t.bytes(), ft, out, flags); } else if (query instanceof TermRangeQuery) { TermRangeQuery q = (TermRangeQuery) query; String fname = q.getField(); FieldType ft = writeFieldName(fname, schema, out, flags); out.append(q.includesLower() ? '[' : '{'); BytesRef lt = q.getLowerTerm(); BytesRef ut = q.getUpperTerm(); if (lt == null) { out.append('*'); } else { writeFieldVal(lt, ft, out, flags); } out.append(" TO "); if (ut == null) { out.append('*'); } else { writeFieldVal(ut, ft, out, flags); } out.append(q.includesUpper() ? ']' : '}'); } else if (query instanceof NumericRangeQuery) { NumericRangeQuery q = (NumericRangeQuery) query; String fname = q.getField(); FieldType ft = writeFieldName(fname, schema, out, flags); out.append(q.includesMin() ? '[' : '{'); Number lt = q.getMin(); Number ut = q.getMax(); if (lt == null) { out.append('*'); } else { out.append(lt.toString()); } out.append(" TO "); if (ut == null) { out.append('*'); } else { out.append(ut.toString()); } out.append(q.includesMax() ? ']' : '}'); } else if (query instanceof BooleanQuery) { BooleanQuery q = (BooleanQuery) query; boolean needParens = false; if (q.getBoost() != 1.0 || q.getMinimumNumberShouldMatch() != 0 || q.isCoordDisabled()) { needParens = true; } if (needParens) { out.append('('); } boolean first = true; for (BooleanClause c : q.clauses()) { if (!first) { out.append(' '); } else { first = false; } if (c.isProhibited()) { out.append('-'); } else if (c.isRequired()) { out.append('+'); } Query subQuery = c.getQuery(); boolean wrapQuery = false; // TODO: may need to put parens around other types // of queries too, depending on future syntax. if (subQuery instanceof BooleanQuery) { wrapQuery = true; } if (wrapQuery) { out.append('('); } toString(subQuery, schema, out, flags); if (wrapQuery) { out.append(')'); } } if (needParens) { out.append(')'); } if (q.getMinimumNumberShouldMatch() > 0) { out.append('~'); out.append(Integer.toString(q.getMinimumNumberShouldMatch())); } if (q.isCoordDisabled()) { out.append("/no_coord"); } } else if (query instanceof PrefixQuery) { PrefixQuery q = (PrefixQuery) query; Term prefix = q.getPrefix(); FieldType ft = writeFieldName(prefix.field(), schema, out, flags); out.append(prefix.text()); out.append('*'); } else if (query instanceof WildcardQuery) { out.append(query.toString()); writeBoost = false; } else if (query instanceof FuzzyQuery) { out.append(query.toString()); writeBoost = false; } else if (query instanceof ConstantScoreQuery) { out.append(query.toString()); writeBoost = false; } else if (query instanceof WrappedQuery) { WrappedQuery q = (WrappedQuery) query; out.append(q.getOptions()); toString(q.getWrappedQuery(), schema, out, flags); writeBoost = false; // we don't use the boost on wrapped queries } else { out.append(query.getClass().getSimpleName() + '(' + query.toString() + ')'); writeBoost = false; } if (writeBoost && query.getBoost() != 1.0f) { out.append("^"); out.append(Float.toString(query.getBoost())); } }
/** * Construct the query (using spans). This method will be called recursively. * * @param q Query * @param scope Author, affiliation, or Reference * @param level Used only for formatting (indentation) the level of recursion * @param andSpans ArrayList of Spans that should be 'and' * @param orSpans ArrayList of Spans that should be 'or' * @param notSpans ArrayList of Spans that should be 'not' * @return SpanQuery */ private SpanQuery buildQuery_recursive( Query q, String scope, int level, ArrayList<SpanQuery> andSpans, ArrayList<SpanQuery> orSpans, ArrayList<SpanQuery> notSpans) { BooleanQuery castQuery = (BooleanQuery) q; String subscope = null; for (BooleanClause clause : castQuery.getClauses()) { Class queryclazz = clause.getQuery().getClass(); System.out.println( repeat(' ', level) + "[" + queryclazz + "][" + clause.getOccur() + "] " + clause.toString()); if (queryclazz == BooleanQuery.class) { System.out.println("Number of Clauses is " + castQuery.clauses().size()); System.out.println("Minimum Number to Match is " + castQuery.getMinimumNumberShouldMatch()); if (subscope == null) { if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add( buildQuery_recursive( clause.getQuery(), scope, level + 1, new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>())); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add( buildQuery_recursive( clause.getQuery(), scope, level + 1, new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>())); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add( buildQuery_recursive( clause.getQuery(), scope, level + 1, new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>())); } } else { ArrayList<SpanQuery> subscopeQuery = new ArrayList<SpanQuery>(); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.BEG_TAG)))); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.END_TAG)))); subscopeQuery.add( buildQuery_recursive( clause.getQuery(), scope, level + 1, new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>(), new ArrayList<SpanQuery>())); if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } } } else if (queryclazz == TermQuery.class) { TermQuery tq = (TermQuery) clause.getQuery(); if (tq.getTerm().field().compareTo(SUBSCOPE_FIELD) == 0) { // Set the subscope subscope = tq.getTerm().text(); // Need to add a term here (otherwise we have problems) WildcardQuery wildcard = new WildcardQuery(new Term(scope, "*")); if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add(new SpanMultiTermQueryWrapper<WildcardQuery>(wildcard)); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add(new SpanMultiTermQueryWrapper<WildcardQuery>(wildcard)); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { notSpans.add(new SpanMultiTermQueryWrapper<WildcardQuery>(wildcard)); } } else if (subscope == null) { if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add(buildTermQuery(scope, tq)); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add(buildTermQuery(scope, tq)); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { notSpans.add(buildTermQuery(scope, tq)); } } else { ArrayList<SpanQuery> subscopeQuery = new ArrayList<SpanQuery>(); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.BEG_TAG)))); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.END_TAG)))); subscopeQuery.add(buildTermQuery(scope, tq)); if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } } } else if (queryclazz == WildcardQuery.class) { if (subscope == null) { if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add(buildWildcardQuery(scope, clause.getQuery())); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add(buildWildcardQuery(scope, clause.getQuery())); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add(buildWildcardQuery(scope, clause.getQuery())); } } else { ArrayList<SpanQuery> subscopeQuery = new ArrayList<SpanQuery>(); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.BEG_TAG)))); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.END_TAG)))); subscopeQuery.add(buildWildcardQuery(scope, clause.getQuery())); if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } } } else if (queryclazz == PrefixQuery.class) { if (subscope == null) { if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add(buildPrefixQuery(scope, clause.getQuery())); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add(buildPrefixQuery(scope, clause.getQuery())); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add(buildPrefixQuery(scope, clause.getQuery())); } } else { ArrayList<SpanQuery> subscopeQuery = new ArrayList<SpanQuery>(); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.BEG_TAG)))); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.END_TAG)))); subscopeQuery.add(buildPrefixQuery(scope, clause.getQuery())); if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } } } else if (queryclazz == PhraseQuery.class) { if (subscope == null) { if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add(buildPhraseQuery(scope, clause.getQuery())); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add(buildPhraseQuery(scope, clause.getQuery())); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add(buildPhraseQuery(scope, clause.getQuery())); } } else { ArrayList<SpanQuery> subscopeQuery = new ArrayList<SpanQuery>(); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.BEG_TAG)))); subscopeQuery.add( new SpanTermQuery(new Term(scope, getTag(scope, subscope, TAG_TYPE.END_TAG)))); subscopeQuery.add(buildPhraseQuery(scope, clause.getQuery())); if (clause.getOccur() == BooleanClause.Occur.MUST) { andSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.SHOULD) { orSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } else if (clause.getOccur() == BooleanClause.Occur.MUST_NOT) { // FIX notSpans.add( new SpanBetweenQuery(subscopeQuery.toArray(new SpanQuery[subscopeQuery.size()]))); } } } else { System.out.println("[" + q.getClass() + "]"); } } ArrayList<SpanQuery> includeSpans = new ArrayList<SpanQuery>(); ; // Add the 'and' queries to the includeSpans (if there were any) if (!andSpans.isEmpty()) { if (andSpans.size() > 1) { includeSpans.add(new SpanAndQuery(andSpans.toArray(new SpanQuery[andSpans.size()]))); } else { includeSpans.add(andSpans.get(0)); } } // Add the 'or' queries to the includeSpans (if there were any) if (!orSpans.isEmpty()) { includeSpans.add(new SpanOrQuery(orSpans.toArray(new SpanQuery[orSpans.size()]))); } // Exclude the 'not' queries from the includeSpans (if there were any) if (!notSpans.isEmpty()) { if (includeSpans.size() > 1) { if (notSpans.size() > 1) { return new SpanNotQuery( new SpanAndQuery(includeSpans.toArray(new SpanQuery[includeSpans.size()])), new SpanAndQuery(notSpans.toArray(new SpanQuery[notSpans.size()]))); } else { return new SpanNotQuery( new SpanAndQuery(includeSpans.toArray(new SpanQuery[includeSpans.size()])), notSpans.get(0)); } } else { if (notSpans.size() > 1) { return new SpanNotQuery( includeSpans.get(0), new SpanAndQuery(notSpans.toArray(new SpanQuery[notSpans.size()]))); } else { return new SpanNotQuery(includeSpans.get(0), notSpans.get(0)); } } } else { if (includeSpans.size() > 1) { return new SpanAndQuery(includeSpans.toArray(new SpanQuery[includeSpans.size()])); } else { return includeSpans.get(0); } } }