You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ja...@apache.org on 2013/05/12 23:23:38 UTC
svn commit: r1481651 - in /lucene/dev/trunk/solr: ./
core/src/java/org/apache/solr/search/ core/src/test/org/apache/solr/search/
Author: janhoy
Date: Sun May 12 21:23:37 2013
New Revision: 1481651
URL: http://svn.apache.org/r1481651
Log:
SOLR-4785: New MaxScoreQParserPlugin
Added:
lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParser.java (with props)
lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParserPlugin.java (with props)
lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java (with props)
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QParserPlugin.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1481651&r1=1481650&r2=1481651&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Sun May 12 21:23:37 2013
@@ -78,6 +78,8 @@ New Features
in cases where exact hit-counts are unnecessary. Also, when "collateExtendedResults"
is false, this optimization is always made (James Dyer).
+* SOLR-4785: New MaxScoreQParserPlugin returning max() instead of sum() of terms (janhoy)
+
Bug Fixes
----------------------
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParser.java?rev=1481651&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParser.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParser.java Sun May 12 21:23:37 2013
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.search;
+
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.DisjunctionMaxQuery;
+import org.apache.lucene.search.Query;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.request.SolrQueryRequest;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @see MaxScoreQParserPlugin
+ */
+public class MaxScoreQParser extends LuceneQParser {
+ float tie = 0.0f;
+
+ public MaxScoreQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
+ super(qstr, localParams, params, req);
+ if (getParam("tie") != null) {
+ tie = Float.parseFloat(getParam("tie"));
+ }
+ }
+
+ /**
+ * Parses the query exactly like the Lucene parser does, but
+ * delegates all SHOULD clauses to DisjunctionMaxQuery with
+ * meaning only the clause with the max score will contribute
+ * to the overall score, unless the tie parameter is specified.
+ * <br/>
+ * The max() is only calculated from the SHOULD clauses.
+ * Any MUST clauses will be passed through as separate
+ * BooleanClauses and thus always contribute to the score.
+ * @return the resulting Query
+ * @throws org.apache.solr.search.SyntaxError if parsing fails
+ */
+ @Override
+ public Query parse() throws SyntaxError {
+ Query q = super.parse();
+ if (!(q instanceof BooleanQuery)) {
+ return q;
+ }
+ BooleanQuery obq = (BooleanQuery)q;
+ Collection<Query> should = new ArrayList<Query>();
+ Collection<BooleanClause> prohibOrReq = new ArrayList<BooleanClause>();
+ BooleanQuery newq = new BooleanQuery();
+
+ for (BooleanClause clause : obq.getClauses()) {
+ if(clause.isProhibited() || clause.isRequired()) {
+ prohibOrReq.add(clause);
+ } else {
+ BooleanQuery bq = new BooleanQuery();
+ bq.add(clause);
+ should.add(bq);
+ }
+ }
+ if (should.size() > 0) {
+ DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(should, tie);
+ newq.add(dmq, BooleanClause.Occur.SHOULD);
+ }
+ for(BooleanClause c : prohibOrReq) {
+ newq.add(c);
+ }
+ return newq;
+ }
+}
\ No newline at end of file
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParserPlugin.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParserPlugin.java?rev=1481651&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParserPlugin.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/MaxScoreQParserPlugin.java Sun May 12 21:23:37 2013
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.search;
+
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.request.SolrQueryRequest;
+
+/**
+ * Parses a query like Lucene query parser, but scoring with max score, not sum
+ * <br>Accepts the "tie" request parameter as with dismax. 0.0=max, 1.0=sum
+ * <br>All other parameters are as with Lucene parser
+ * <br>Example: <code>q=foo {!maxscore v=$myq}&myq=A OR B OR C</code>
+ */
+public class MaxScoreQParserPlugin extends LuceneQParserPlugin {
+ public static String NAME = "maxscore";
+
+ @Override
+ public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
+ return new MaxScoreQParser(qstr, localParams, params, req);
+ }
+}
+
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QParserPlugin.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QParserPlugin.java?rev=1481651&r1=1481650&r2=1481651&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QParserPlugin.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QParserPlugin.java Sun May 12 21:23:37 2013
@@ -43,6 +43,7 @@ public abstract class QParserPlugin impl
JoinQParserPlugin.NAME, JoinQParserPlugin.class,
SurroundQParserPlugin.NAME, SurroundQParserPlugin.class,
SwitchQParserPlugin.NAME, SwitchQParserPlugin.class,
+ MaxScoreQParserPlugin.NAME, MaxScoreQParserPlugin.class
};
/** return a {@link QParser} */
Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java?rev=1481651&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java Sun May 12 21:23:37 2013
@@ -0,0 +1,117 @@
+package org.apache.solr.search;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.search.*;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.util.AbstractSolrTestCase;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class TestMaxScoreQueryParser extends AbstractSolrTestCase {
+ Query q;
+ BooleanClause[] clauses;
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ initCore("solrconfig.xml", "schema.xml");
+ }
+
+ @Test
+ public void testFallbackToLucene() {
+ q = parse("foo");
+ assertTrue(q instanceof TermQuery);
+
+ q = parse("price:[0 TO 10]");
+ assertTrue(q instanceof NumericRangeQuery);
+ }
+
+ @Test
+ public void testNoShouldClauses() {
+ q = parse("+foo +bar");
+ clauses = clauses(q);
+ assertEquals(2, clauses.length);
+ assertTrue(clauses[0].isRequired());
+ assertTrue(clauses[1].isRequired());
+
+ q = parse("+foo -bar");
+ clauses = clauses(q);
+ assertEquals(2, clauses.length);
+ assertTrue(clauses[0].isRequired());
+ assertTrue(clauses[1].isProhibited());
+ }
+
+ @Test
+ public void testPureMax() {
+ q = parse("foo bar");
+ clauses = clauses(q);
+ assertEquals(1, clauses.length);
+ assertTrue(clauses[0].getQuery() instanceof DisjunctionMaxQuery);
+ assertEquals(0.0, ((DisjunctionMaxQuery) clauses[0].getQuery()).getTieBreakerMultiplier(), 1e-15);
+ ArrayList<Query> qa = ((DisjunctionMaxQuery) clauses[0].getQuery()).getDisjuncts();
+ assertEquals(2, qa.size());
+ assertEquals("text:foo", qa.get(0).toString());
+ }
+
+ @Test
+ public void testMaxAndProhibited() {
+ q = parse("foo bar -baz");
+ clauses = clauses(q);
+ assertEquals(2, clauses.length);
+ assertTrue(clauses[0].getQuery() instanceof DisjunctionMaxQuery);
+ assertTrue(clauses[1].getQuery() instanceof TermQuery);
+ assertEquals("text:baz", clauses[1].getQuery().toString());
+ assertTrue(clauses[1].isProhibited());
+ }
+
+ @Test
+ public void testTie() {
+ q = parse("foo bar", "tie", "0.5");
+ clauses = clauses(q);
+ assertEquals(1, clauses.length);
+ assertTrue(clauses[0].getQuery() instanceof DisjunctionMaxQuery);
+ assertEquals(0.5, ((DisjunctionMaxQuery) clauses[0].getQuery()).getTieBreakerMultiplier(), 1e-15);
+ }
+
+ //
+ // Helper methods
+ //
+
+ private Query parse(String q, String... params) {
+ try {
+ ModifiableSolrParams p = new ModifiableSolrParams();
+ ArrayList<String> al = new ArrayList<String>(Arrays.asList(params));
+ while(al.size() >= 2) {
+ p.add(al.remove(0), al.remove(0));
+ }
+ return new MaxScoreQParser(q, p, new ModifiableSolrParams(), req(q)).parse();
+ } catch (SyntaxError syntaxError) {
+ fail("Failed with exception "+syntaxError.getMessage());
+ }
+ fail("Parse failed");
+ return null;
+ }
+
+ private BooleanClause[] clauses(Query q) {
+ return ((BooleanQuery) q).getClauses();
+ }
+}