LUCENE-8143: Remove no-op SpanBoostQuery (#155)

Boosts are ignored on inner span queries, and top-level boosts can
be applied by using a normal BoostQuery, so SpanBoostQuery
itself is redundant and trappy. This commit removes it entirely.
This commit is contained in:
Alan Woodward 2021-06-07 15:56:16 +01:00 committed by GitHub
parent 428d2d99d7
commit dbb4c265d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 92 additions and 313 deletions

View File

@ -128,6 +128,8 @@ API Changes
* LUCENE-9962: DrillSideways allows sub-classes to provide "drill down" FacetsCollectors. They
may provide a null collector if they choose to bypass "drill down" facet collection. (Greg Miller)
* LUCENE-8143: SpanBoostQuery has been removed. (Alan Woodward)
Improvements
* LUCENE-9960: Avoid unnecessary top element replacement for equal elements in PriorityQueue. (Dawid Weiss)

View File

@ -410,3 +410,8 @@ be as simple as no longer providing this boolean.
## SpanQuery and subclasses have moved from core/ to the queries module
They can now be found in the o.a.l.queries.spans package.
## SpanBoostQuery has been removed (LUCENE-8143)
SpanBoostQuery was a no-op unless used at the top level of a SpanQuery nested
structure. Use a standard BoostQuery here instead.

View File

@ -36,7 +36,6 @@ import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanFirstQuery;
import org.apache.lucene.queries.spans.SpanMultiTermQueryWrapper;
import org.apache.lucene.queries.spans.SpanNearQuery;
@ -563,10 +562,7 @@ public class TestUnifiedHighlighterMTQ extends LuceneTestCase {
IndexSearcher searcher = newSearcher(ir);
UnifiedHighlighter highlighter = randomUnifiedHighlighter(searcher, indexAnalyzer);
// wrap in a SpanBoostQuery to also show we see inside it
Query query =
new SpanBoostQuery(
new SpanMultiTermQueryWrapper<>(new WildcardQuery(new Term("body", "te*"))), 2.0f);
Query query = new SpanMultiTermQueryWrapper<>(new WildcardQuery(new Term("body", "te*")));
TopDocs topDocs = searcher.search(query, 10, Sort.INDEXORDER);
assertEquals(2, topDocs.totalHits.value);
String snippets[] = highlighter.highlight("body", query, topDocs);

View File

@ -23,7 +23,6 @@ import java.util.HashSet;
import java.util.Set;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.FieldMaskingSpanQuery;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanContainingQuery;
import org.apache.lucene.queries.spans.SpanFirstQuery;
import org.apache.lucene.queries.spans.SpanMultiTermQueryWrapper;
@ -122,12 +121,6 @@ public class TestSpanExtractors extends LuceneTestCase {
assertEquals(Collections.singleton(t3), collectTerms(swq));
}
public void testSpanBoost() {
Term t1 = new Term("field", "term1");
SpanBoostQuery q = new SpanBoostQuery(new SpanTermQuery(t1), 0.1f);
assertEquals(Collections.singleton(t1), collectTerms(q));
}
public void testFieldMaskingSpanQuery() {
Term t1 = new Term("field", "term1");
FieldMaskingSpanQuery q = new FieldMaskingSpanQuery(new SpanTermQuery(t1), "field2");

View File

@ -1,118 +0,0 @@
/*
* 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.lucene.queries.spans;
import java.io.IOException;
import java.util.Objects;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryVisitor;
import org.apache.lucene.search.ScoreMode;
/** Counterpart of {@link BoostQuery} for spans. */
public final class SpanBoostQuery extends SpanQuery {
private final SpanQuery query;
private final float boost;
/**
* Sole constructor: wrap {@code query} in such a way that the produced scores will be boosted by
* {@code boost}.
*/
public SpanBoostQuery(SpanQuery query, float boost) {
this.query = Objects.requireNonNull(query);
this.boost = boost;
}
/** Return the wrapped {@link SpanQuery}. */
public SpanQuery getQuery() {
return query;
}
/** Return the applied boost. */
public float getBoost() {
return boost;
}
@Override
public boolean equals(Object other) {
return sameClassAs(other) && equalsTo(getClass().cast(other));
}
private boolean equalsTo(SpanBoostQuery other) {
return query.equals(other.query)
&& Float.floatToIntBits(boost) == Float.floatToIntBits(other.boost);
}
@Override
public int hashCode() {
int h = classHash();
h = 31 * h + query.hashCode();
h = 31 * h + Float.floatToIntBits(boost);
return h;
}
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (boost == 1f) {
return query;
}
final SpanQuery rewritten = (SpanQuery) query.rewrite(reader);
if (query != rewritten) {
return new SpanBoostQuery(rewritten, boost);
}
if (query.getClass() == SpanBoostQuery.class) {
SpanBoostQuery in = (SpanBoostQuery) query;
return new SpanBoostQuery(in.query, boost * in.boost);
}
return super.rewrite(reader);
}
@Override
public void visit(QueryVisitor visitor) {
if (visitor.acceptField(getField())) {
query.visit(visitor.getSubVisitor(BooleanClause.Occur.MUST, this));
}
}
@Override
public String toString(String field) {
StringBuilder builder = new StringBuilder();
builder.append("(");
builder.append(query.toString(field));
builder.append(")^");
builder.append(boost);
return builder.toString();
}
@Override
public String getField() {
return query.getField();
}
@Override
public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost)
throws IOException {
return query.createWeight(searcher, scoreMode, SpanBoostQuery.this.boost * boost);
}
}

View File

@ -17,7 +17,6 @@
package org.apache.lucene.queries.payloads;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanNearQuery;
import org.apache.lucene.queries.spans.SpanOrQuery;
import org.apache.lucene.queries.spans.SpanQuery;
@ -49,26 +48,12 @@ public class TestPayloadExplanations extends BaseExplanationTestCase {
}
}
public void testPT2() throws Exception {
for (PayloadFunction fn : functions) {
SpanQuery q = pt("w1", fn);
qtest(new SpanBoostQuery(q, 1000), new int[] {0, 1, 2, 3});
}
}
public void testPT4() throws Exception {
for (PayloadFunction fn : functions) {
qtest(pt("xx", fn), new int[] {2, 3});
}
}
public void testPT5() throws Exception {
for (PayloadFunction fn : functions) {
SpanQuery q = pt("xx", fn);
qtest(new SpanBoostQuery(q, 1000), new int[] {2, 3});
}
}
/*
protected static final String[] docFields = {
"w1 w2 w3 w4 w5",

View File

@ -1,50 +0,0 @@
/*
* 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.lucene.queries.spans;
import org.apache.lucene.index.Term;
import org.apache.lucene.util.LuceneTestCase;
public class TestSpanBoostQuery extends LuceneTestCase {
public void testEquals() {
final float boost = random().nextFloat() * 3 - 1;
SpanTermQuery q = new SpanTermQuery(new Term("foo", "bar"));
SpanBoostQuery q1 = new SpanBoostQuery(q, boost);
SpanBoostQuery q2 = new SpanBoostQuery(q, boost);
assertEquals(q1, q2);
assertEquals(q1.getBoost(), q2.getBoost(), 0f);
float boost2 = boost;
while (boost == boost2) {
boost2 = random().nextFloat() * 3 - 1;
}
SpanBoostQuery q3 = new SpanBoostQuery(q, boost2);
assertFalse(q1.equals(q3));
assertFalse(q1.hashCode() == q3.hashCode());
}
public void testToString() {
assertEquals(
"(foo:bar)^2.0",
new SpanBoostQuery(new SpanTermQuery(new Term("foo", "bar")), 2).toString());
SpanOrQuery bq =
new SpanOrQuery(
new SpanTermQuery(new Term("foo", "bar")), new SpanTermQuery(new Term("foo", "baz")));
assertEquals("(spanOr([foo:bar, foo:baz]))^2.0", new SpanBoostQuery(bq, 2).toString());
}
}

View File

@ -46,11 +46,6 @@ public class TestSpanExplanations extends BaseSpanExplanationTestCase {
qtest(new BoostQuery(q, 1000), new int[] {0, 1, 2, 3});
}
public void testST3() throws Exception {
SpanQuery q = st("w1");
bqtest(new SpanBoostQuery(q, 0), new int[] {0, 1, 2, 3});
}
public void testST4() throws Exception {
SpanQuery q = st("xx");
qtest(q, new int[] {2, 3});
@ -61,11 +56,6 @@ public class TestSpanExplanations extends BaseSpanExplanationTestCase {
qtest(new BoostQuery(q, 1000), new int[] {2, 3});
}
public void testST6() throws Exception {
SpanQuery q = st("xx");
qtest(new SpanBoostQuery(q, 0), new int[] {2, 3});
}
/* some SpanFirstQueries */
public void testSF1() throws Exception {
@ -78,11 +68,6 @@ public class TestSpanExplanations extends BaseSpanExplanationTestCase {
qtest(new BoostQuery(q, 1000), new int[] {0, 1, 2, 3});
}
public void testSF3() throws Exception {
SpanQuery q = sf(("w1"), 1);
bqtest(new SpanBoostQuery(q, 0), new int[] {0, 1, 2, 3});
}
public void testSF4() throws Exception {
SpanQuery q = sf(("xx"), 2);
qtest(q, new int[] {2});
@ -98,11 +83,6 @@ public class TestSpanExplanations extends BaseSpanExplanationTestCase {
qtest(new BoostQuery(q, 1000), new int[] {2});
}
public void testSF7() throws Exception {
SpanQuery q = sf(("xx"), 3);
bqtest(new SpanBoostQuery(q, 0), new int[] {2, 3});
}
/* some SpanOrQueries */
public void testSO1() throws Exception {
@ -194,11 +174,6 @@ public class TestSpanExplanations extends BaseSpanExplanationTestCase {
qtest(new BoostQuery(q, 1000), new int[] {0, 1, 2, 3});
}
public void testSNot3() throws Exception {
SpanQuery q = snot(sf("w1", 10), st("QQ"));
bqtest(new SpanBoostQuery(q, 0), new int[] {0, 1, 2, 3});
}
public void testSNot4() throws Exception {
SpanQuery q = snot(sf("w1", 10), st("xx"));
qtest(q, new int[] {0, 1, 2, 3});
@ -209,33 +184,12 @@ public class TestSpanExplanations extends BaseSpanExplanationTestCase {
qtest(new BoostQuery(q, 1000), new int[] {0, 1, 2, 3});
}
public void testSNot6() throws Exception {
SpanQuery q = snot(sf("w1", 10), st("xx"));
bqtest(new SpanBoostQuery(q, 0), new int[] {0, 1, 2, 3});
}
public void testSNot7() throws Exception {
SpanQuery f = snear("w1", "w3", 10, true);
SpanQuery q = snot(f, st("xx"));
qtest(q, new int[] {0, 1, 3});
}
public void testSNot8() throws Exception {
// NOTE: using qtest not bqtest
SpanQuery f = snear("w1", "w3", 10, true);
f = new SpanBoostQuery(f, 0);
SpanQuery q = snot(f, st("xx"));
qtest(q, new int[] {0, 1, 3});
}
public void testSNot9() throws Exception {
// NOTE: using qtest not bqtest
SpanQuery t = st("xx");
t = new SpanBoostQuery(t, 0);
SpanQuery q = snot(snear("w1", "w3", 10, true), t);
qtest(q, new int[] {0, 1, 3});
}
public void testSNot10() throws Exception {
SpanQuery t = st("xx");
SpanQuery q = snot(snear("w1", "w3", 10, true), t);

View File

@ -463,18 +463,4 @@ public class TestSpanSearchEquivalence extends SearchEquivalenceTestBase {
Query q2 = spanQuery(new SpanContainingQuery(nearQuery, termQuery));
assertSameSet(q1, q2);
}
public void testSpanBoostQuerySimplification() throws Exception {
float b1 = random().nextFloat() * 10;
float b2 = random().nextFloat() * 10;
Term term = randomTerm();
Query q1 = new SpanBoostQuery(new SpanBoostQuery(new SpanTermQuery(term), b2), b1);
// Use AssertingQuery to prevent BoostQuery from merging inner and outer boosts
Query q2 =
new SpanBoostQuery(
new AssertingSpanQuery(new SpanBoostQuery(new SpanTermQuery(term), b2)), b1);
assertSameScores(q1, q2);
}
}

View File

@ -24,7 +24,6 @@ import java.util.Objects;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanNearQuery;
import org.apache.lucene.queries.spans.SpanNotQuery;
import org.apache.lucene.queries.spans.SpanOrQuery;
@ -380,10 +379,8 @@ public class ComplexPhraseQueryParser extends QueryParser {
for (BooleanClause clause : qc) {
Query childQuery = clause.getQuery();
float boost = 1f;
while (childQuery instanceof BoostQuery) {
BoostQuery bq = (BoostQuery) childQuery;
boost *= bq.getBoost();
childQuery = bq.getQuery();
}
@ -396,9 +393,6 @@ public class ComplexPhraseQueryParser extends QueryParser {
if (childQuery instanceof TermQuery) {
TermQuery tq = (TermQuery) childQuery;
SpanQuery stq = new SpanTermQuery(tq.getTerm());
if (boost != 1f) {
stq = new SpanBoostQuery(stq, boost);
}
chosenList.add(stq);
} else if (childQuery instanceof BooleanQuery) {
BooleanQuery cbq = (BooleanQuery) childQuery;

View File

@ -56,7 +56,6 @@ import java.util.HashMap;
import java.util.Iterator;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanOrQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queries.spans.SpanTermQuery;
@ -115,11 +114,6 @@ public class SpanNearClauseFactory { // FIXME: rename to SpanClauseFactory
if (!(q instanceof SpanQuery))
throw new AssertionError("Expected SpanQuery: " + q.toString(getFieldName()));
float boost = 1f;
if (q instanceof SpanBoostQuery) {
SpanBoostQuery bq = (SpanBoostQuery) q;
boost = bq.getBoost();
q = bq.getQuery();
}
addSpanQueryWeighted((SpanQuery) q, boost);
}
@ -129,10 +123,6 @@ public class SpanNearClauseFactory { // FIXME: rename to SpanClauseFactory
int i = 0;
while (sqi.hasNext()) {
SpanQuery sq = sqi.next();
float boost = weightBySpanQuery.get(sq);
if (boost != 1f) {
sq = new SpanBoostQuery(sq, boost);
}
spanQueries[i++] = sq;
}

View File

@ -20,7 +20,6 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.queries.payloads.AveragePayloadFunction;
import org.apache.lucene.queries.payloads.PayloadDecoder;
import org.apache.lucene.queries.payloads.PayloadScoreQuery;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
@ -36,12 +35,9 @@ public class BoostingTermBuilder extends SpanBuilderBase {
String value = DOMUtils.getNonBlankTextOrFail(e);
// TODO make function and decoder pluggable somehow?
SpanQuery btq =
new PayloadScoreQuery(
new SpanTermQuery(new Term(fieldName, value)),
new AveragePayloadFunction(),
PayloadDecoder.FLOAT_DECODER);
btq = new SpanBoostQuery(btq, DOMUtils.getAttribute(e, "boost", 1.0f));
return btq;
return new PayloadScoreQuery(
new SpanTermQuery(new Term(fieldName, value)),
new AveragePayloadFunction(),
PayloadDecoder.FLOAT_DECODER);
}
}

View File

@ -17,7 +17,9 @@
package org.apache.lucene.queryparser.xml.builders;
import org.apache.lucene.queries.spans.SpanQuery; // javadocs
import org.apache.lucene.queryparser.xml.DOMUtils;
import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.Query;
import org.w3c.dom.Element;
@ -26,6 +28,11 @@ public abstract class SpanBuilderBase implements SpanQueryBuilder {
@Override
public Query getQuery(Element e) throws ParserException {
return getSpanQuery(e);
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
SpanQuery q = getSpanQuery(e);
if (boost == 1.0f) {
return q;
}
return new BoostQuery(q, boost);
}
}

View File

@ -16,7 +16,6 @@
*/
package org.apache.lucene.queryparser.xml.builders;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanFirstQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
@ -38,9 +37,6 @@ public class SpanFirstBuilder extends SpanBuilderBase {
Element child = DOMUtils.getFirstChildElement(e);
SpanQuery q = factory.getSpanQuery(child);
SpanFirstQuery sfq = new SpanFirstQuery(q, end);
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
return new SpanBoostQuery(sfq, boost);
return new SpanFirstQuery(q, end);
}
}

View File

@ -18,7 +18,6 @@ package org.apache.lucene.queryparser.xml.builders;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanNearQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
@ -47,8 +46,6 @@ public class SpanNearBuilder extends SpanBuilderBase {
}
}
SpanQuery[] spanQueries = spans.toArray(new SpanQuery[spans.size()]);
SpanQuery snq = new SpanNearQuery(spanQueries, slop, inOrder);
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
return new SpanBoostQuery(snq, boost);
return new SpanNearQuery(spanQueries, slop, inOrder);
}
}

View File

@ -16,7 +16,6 @@
*/
package org.apache.lucene.queryparser.xml.builders;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanNotQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
@ -43,9 +42,6 @@ public class SpanNotBuilder extends SpanBuilderBase {
SpanQuery include = factory.getSpanQuery(includeElem);
SpanQuery exclude = factory.getSpanQuery(excludeElem);
SpanNotQuery snq = new SpanNotQuery(include, exclude);
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
return new SpanBoostQuery(snq, boost);
return new SpanNotQuery(include, exclude);
}
}

View File

@ -18,10 +18,8 @@ package org.apache.lucene.queryparser.xml.builders;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanOrQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
import org.apache.lucene.queryparser.xml.ParserException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@ -45,8 +43,6 @@ public class SpanOrBuilder extends SpanBuilderBase {
}
}
SpanQuery[] clauses = clausesList.toArray(new SpanQuery[clausesList.size()]);
SpanOrQuery soq = new SpanOrQuery(clauses);
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
return new SpanBoostQuery(soq, boost);
return new SpanOrQuery(clauses);
}
}

View File

@ -23,7 +23,6 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanOrQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queries.spans.SpanTermQuery;
@ -57,9 +56,7 @@ public class SpanOrTermsBuilder extends SpanBuilderBase {
clausesList.add(stq);
}
ts.end();
SpanOrQuery soq = new SpanOrQuery(clausesList.toArray(new SpanQuery[clausesList.size()]));
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
return new SpanBoostQuery(soq, boost);
return new SpanOrQuery(clausesList.toArray(new SpanQuery[clausesList.size()]));
} catch (IOException ioe) {
throw new ParserException("IOException parsing value:" + value, ioe);
}

View File

@ -16,7 +16,6 @@
*/
package org.apache.lucene.queryparser.xml.builders;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanPositionRangeQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
@ -39,9 +38,6 @@ public class SpanPositionRangeBuilder extends SpanBuilderBase {
Element child = DOMUtils.getFirstChildElement(e);
SpanQuery q = factory.getSpanQuery(child);
SpanPositionRangeQuery query = new SpanPositionRangeQuery(q, start, end);
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
return new SpanBoostQuery(query, boost);
return new SpanPositionRangeQuery(q, start, end);
}
}

View File

@ -17,7 +17,6 @@
package org.apache.lucene.queryparser.xml.builders;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanBoostQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
@ -31,9 +30,6 @@ public class SpanTermBuilder extends SpanBuilderBase {
public SpanQuery getSpanQuery(Element e) throws ParserException {
String fieldName = DOMUtils.getAttributeWithInheritanceOrFail(e, "fieldName");
String value = DOMUtils.getNonBlankTextOrFail(e);
SpanTermQuery stq = new SpanTermQuery(new Term(fieldName, value));
float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
return new SpanBoostQuery(stq, boost);
return new SpanTermQuery(new Term(fieldName, value));
}
}

View File

@ -20,11 +20,17 @@ import java.util.HashSet;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.analysis.MockSynonymAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanNearQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
@ -205,6 +211,27 @@ public class TestComplexPhraseQuery extends LuceneTestCase {
assertTrue(!q2.equals(q));
}
public void testBoosts() throws Exception {
// top-level boosts should be preserved, interior boosts are ignored as they don't apply to
// spans
String topLevel = "(\"john^3 smit*\"~4)^2";
ComplexPhraseQueryParser parser = new ComplexPhraseQueryParser("name", new StandardAnalyzer());
parser.setInOrder(true);
Query actual = searcher.rewrite(parser.parse(topLevel));
Query expected =
new BoostQuery(
new SpanNearQuery(
new SpanQuery[] {
new SpanTermQuery(new Term("name", "john")),
new SpanTermQuery(new Term("name", "smith"))
},
4,
true),
2);
assertEquals(expected, actual);
}
@Override
public void setUp() throws Exception {
super.setUp();

View File

@ -16,8 +16,10 @@
*/
package org.apache.lucene.queryparser.xml;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer;
@ -26,7 +28,10 @@ import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.spans.SpanNearQuery;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@ -201,6 +206,39 @@ public class TestCoreParser extends LuceneTestCase {
dumpResults("PointRangeQueryWithoutRange", q, 5);
}
public void testSpanBoosts() throws Exception {
String topLevel = "<SpanTerm fieldName=\"field\" boost=\"2\">value</SpanTerm>";
try (ByteArrayInputStream is =
new ByteArrayInputStream(topLevel.getBytes(StandardCharsets.UTF_8))) {
Query actual = coreParser().parse(is);
Query expected = new BoostQuery(new SpanTermQuery(new Term("field", "value")), 2);
assertEquals(expected, actual);
}
String nested =
"<SpanNear fieldName=\"field\" boost=\"2\" slop=\"8\" inOrder=\"false\">"
+ // top level boost is preserved
" <SpanTerm boost=\"4\">value1</SpanTerm>"
+ // interior boost is ignored
" <SpanTerm>value2</SpanTerm>"
+ "</SpanNear>";
try (ByteArrayInputStream is =
new ByteArrayInputStream(nested.getBytes(StandardCharsets.UTF_8))) {
Query actual = coreParser().parse(is);
Query expected =
new BoostQuery(
new SpanNearQuery(
new SpanQuery[] {
new SpanTermQuery(new Term("field", "value1")),
new SpanTermQuery(new Term("field", "value2"))
},
8,
false),
2);
assertEquals(expected, actual);
}
}
// ================= Helper methods ===================================
protected String defaultField() {