Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions solr/core/src/java/org/apache/solr/search/BoolQParserPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.solr.common.params.DisMaxParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.query.FilterQuery;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.join.FiltersQParser;
import org.apache.solr.util.SolrPluginUtils;

/**
* Create a boolean query from sub queries. Sub queries can be marked as {@code must}, {@code
Expand All @@ -46,10 +48,12 @@ public Query parse() throws SyntaxError {
}

@Override
protected BooleanQuery.Builder createBuilder() {
BooleanQuery.Builder builder = super.createBuilder();
builder.setMinimumNumberShouldMatch(localParams.getInt("mm", 0));
return builder;
protected BooleanQuery parseImpl() throws SyntaxError {
BooleanQuery query = super.parseImpl();
SolrParams solrParams = SolrParams.wrapDefaults(localParams, params);
String minShouldMatch = SolrPluginUtils.parseMinShouldMatch(req.getSchema(), solrParams);
boolean mmAutoRelax = params.getBool(DisMaxParams.MM_AUTORELAX, false);
return SolrPluginUtils.setMinShouldMatch(query, minShouldMatch, mmAutoRelax);
}

@Override
Expand Down
16 changes: 1 addition & 15 deletions solr/core/src/java/org/apache/solr/search/DisMaxQParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.parser.QueryParser;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.util.SolrPluginUtils;
Expand All @@ -47,19 +46,6 @@ public class DisMaxQParser extends QParser {
*/
private static String IMPOSSIBLE_FIELD_NAME = "\uFFFC\uFFFC\uFFFC";

/**
* Applies the appropriate default rules for the "mm" param based on the effective value of the
* "q.op" param
*
* @see QueryParsing#OP
* @see DisMaxParams#MM
*/
public static String parseMinShouldMatch(final IndexSchema schema, final SolrParams params) {
QueryParser.Operator op = QueryParsing.parseOP(params.get(QueryParsing.OP));

return params.get(DisMaxParams.MM, op.equals(QueryParser.Operator.AND) ? "100%" : "0%");
}

/**
* Uses {@link SolrPluginUtils#parseFieldBoosts(String)} with the 'qf' parameter. Falls back to
* the 'df' parameter
Expand Down Expand Up @@ -248,7 +234,7 @@ protected Query getUserQuery(
String userQuery, SolrPluginUtils.DisjunctionMaxQueryParser up, SolrParams solrParams)
throws SyntaxError {

String minShouldMatch = parseMinShouldMatch(req.getSchema(), solrParams);
String minShouldMatch = SolrPluginUtils.parseMinShouldMatch(req.getSchema(), solrParams);
Query dis = up.parse(userQuery);
Query query = dis;

Expand Down
14 changes: 14 additions & 0 deletions solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.apache.lucene.search.Sort;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.DisMaxParams;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.CollectionUtil;
Expand Down Expand Up @@ -605,6 +606,19 @@ public static void setMinShouldMatch(BooleanQuery.Builder q, String spec, boolea
}
}

/**
* Applies the appropriate default rules for the "mm" param based on the effective value of the
* "q.op" param
*
* @see QueryParsing#OP
* @see DisMaxParams#MM
*/
public static String parseMinShouldMatch(final IndexSchema schema, final SolrParams params) {
QueryParser.Operator op = QueryParsing.parseOP(params.get(QueryParsing.OP));

return params.get(DisMaxParams.MM, op.equals(QueryParser.Operator.AND) ? "100%" : "0%");
}

public static void setMinShouldMatch(BooleanQuery.Builder q, String spec) {
setMinShouldMatch(q, spec, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@

public class TestMmBoolQParserPlugin extends SolrTestCaseJ4 {

private static BooleanQuery.Builder shouldBuilder(String... terms) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
for (String term : terms) {
builder.add(new TermQuery(new Term("name", term)), BooleanClause.Occur.SHOULD);
}
return builder;
}

@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig.xml", "schema.xml");
Expand Down Expand Up @@ -61,12 +69,55 @@ public void testMinShouldMatch() throws Exception {
parseQuery(req("q", "{!bool should=name:foo should=name:bar should=name:qux mm=2}"));

BooleanQuery expected =
new BooleanQuery.Builder()
.add(new TermQuery(new Term("name", "foo")), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term("name", "bar")), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term("name", "qux")), BooleanClause.Occur.SHOULD)
.setMinimumNumberShouldMatch(2)
.build();
shouldBuilder("foo", "bar", "qux").setMinimumNumberShouldMatch(2).build();

assertEquals(expected, actual);
}

@Test
public void testMinShouldMatchPercentage75() throws Exception {
Query actual =
parseQuery(req("q", "{!bool should=name:foo should=name:bar should=name:qux mm=75%}"));

BooleanQuery expected =
shouldBuilder("foo", "bar", "qux").setMinimumNumberShouldMatch(2).build();

assertEquals(expected, actual);
}

@Test
public void testMinShouldMatchPercentage50() throws Exception {
Query actual =
parseQuery(req("q", "{!bool should=name:foo should=name:bar should=name:qux mm=50%}"));

BooleanQuery expected =
shouldBuilder("foo", "bar", "qux").setMinimumNumberShouldMatch(1).build();

assertEquals(expected, actual);
}

@Test
public void testMinShouldMatchThresholdsLower() throws Exception {
Query actual =
parseQuery(
req("q", "{!bool should=name:foo should=name:bar should=name:qux mm='2<-1 5<-2'}"));

BooleanQuery expected =
shouldBuilder("foo", "bar", "qux").setMinimumNumberShouldMatch(2).build();

assertEquals(expected, actual);
}

@Test
public void testMinShouldMatchThresholdsUpper() throws Exception {
Query actual =
parseQuery(
req(
"q",
"{!bool should=name:foo should=name:bar should=name:qux should=name:n1 should=name:n2 should=name:n3 mm='2<-1 5<-2'}"));

BooleanQuery expected =
shouldBuilder("foo", "bar", "qux", "n1", "n2", "n3").setMinimumNumberShouldMatch(4).build();

assertEquals(expected, actual);
}
Expand Down Expand Up @@ -102,11 +153,6 @@ public void testExcludeTags() throws Exception {

@Test
public void testInvalidMinShouldMatchThrowsException() {
expectThrows(
SolrException.class,
NumberFormatException.class,
() -> parseQuery(req("q", "{!bool should=name:foo mm=20%}")));

expectThrows(
SolrException.class,
NumberFormatException.class,
Expand Down
Loading