| package org.apache.lucene.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 java.io.IOException; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import org.apache.lucene.document.Document; |
| import org.apache.lucene.document.Field; |
| import org.apache.lucene.document.StringField; |
| import org.apache.lucene.index.DirectoryReader; |
| import org.apache.lucene.index.FieldInvertState; |
| import org.apache.lucene.index.IndexWriter; |
| import org.apache.lucene.index.IndexWriterConfig; |
| import org.apache.lucene.index.LeafReaderContext; |
| import org.apache.lucene.index.Term; |
| import org.apache.lucene.search.similarities.Similarity; |
| import org.apache.lucene.store.Directory; |
| import org.apache.lucene.util.BytesRef; |
| import org.apache.lucene.util.LuceneTestCase; |
| import org.junit.AfterClass; |
| import org.junit.BeforeClass; |
| |
| /** |
| * Tests coord() computation by BooleanQuery |
| */ |
| public class TestBooleanCoord extends LuceneTestCase { |
| static Directory dir; |
| static DirectoryReader reader; |
| static IndexSearcher searcher; |
| |
| @BeforeClass |
| public static void beforeClass() throws Exception { |
| dir = newDirectory(); |
| IndexWriter iw = new IndexWriter(dir, new IndexWriterConfig(null)); |
| |
| // we only add two documents for testing: |
| // the first document has 3 terms A,B,C (for positive matching). we test scores against this. |
| // the second document has 3 negative terms 1,2,3 that exist in the segment (for non-null scorers) |
| // to test terms that don't exist (null scorers), we use X,Y,Z |
| |
| Document doc = new Document(); |
| doc.add(new StringField("field", "A", Field.Store.NO)); |
| doc.add(new StringField("field", "B", Field.Store.NO)); |
| doc.add(new StringField("field", "C", Field.Store.NO)); |
| iw.addDocument(doc); |
| |
| doc = new Document(); |
| doc.add(new StringField("field", "1", Field.Store.NO)); |
| doc.add(new StringField("field", "2", Field.Store.NO)); |
| doc.add(new StringField("field", "3", Field.Store.NO)); |
| iw.addDocument(doc); |
| |
| iw.close(); |
| reader = DirectoryReader.open(dir); |
| searcher = new IndexSearcher(reader); |
| // we set a similarity that just returns 1, the idea is to test coord |
| searcher.setSimilarity(new Similarity() { |
| @Override |
| public float coord(int overlap, int maxOverlap) { |
| // we use a rather bogus/complex coord, because today coord() can really return anything. |
| // note in the case of overlap == maxOverlap == 1: BooleanWeight always applies 1, (see LUCENE-4300). |
| return overlap / (float)(maxOverlap + 1); |
| } |
| |
| @Override |
| public long computeNorm(FieldInvertState state) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public SimWeight computeWeight(CollectionStatistics collectionStats, TermStatistics... termStats) { |
| return new SimWeight() { |
| @Override |
| public float getValueForNormalization() { |
| return 1f; |
| } |
| |
| @Override |
| public void normalize(float queryNorm, float topLevelBoost) {} |
| }; |
| } |
| |
| @Override |
| public SimScorer simScorer(SimWeight weight, LeafReaderContext context) throws IOException { |
| return new SimScorer() { |
| @Override |
| public float score(int doc, float freq) { |
| return 1; |
| } |
| |
| @Override |
| public float computeSlopFactor(int distance) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public float computePayloadFactor(int doc, int start, int end, BytesRef payload) { |
| throw new AssertionError(); |
| } |
| }; |
| } |
| }); |
| } |
| |
| @AfterClass |
| public static void afterClass() throws Exception { |
| reader.close(); |
| reader = null; |
| dir.close(); |
| dir = null; |
| searcher = null; |
| } |
| |
| // disjunctions |
| |
| public void testDisjunction1TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| // LUCENE-4300: coord(1,1) is always treated as 1 |
| assertScore(1 * 1, bq.build()); |
| } |
| |
| public void testDisjunction2TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(2f + 1), bq.build()); |
| } |
| |
| public void testDisjunction1OutOf2() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(2f + 1), bq.build()); |
| } |
| |
| public void testDisjunction1OutOf2Missing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(2f + 1), bq.build()); |
| } |
| |
| public void testDisjunction1OutOf3() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testDisjunction1OutOf3MissingOne() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testDisjunction1OutOf3MissingTwo() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Y"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testDisjunction2OutOf3() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| public void testDisjunction2OutOf3Missing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| // disjunctions with coord disabled |
| |
| public void testDisjunction1TermMatchesCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testDisjunction2TermMatchesCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testDisjunction1OutOf2CoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testDisjunction1OutOf2MissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testDisjunction1OutOf3CoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testDisjunction1OutOf3MissingOneCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testDisjunction1OutOf3MissingTwoCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Y"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testDisjunction2OutOf3CoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testDisjunction2OutOf3MissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| // minShouldMatch |
| public void testMinShouldMatch1TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| // LUCENE-4300: coord(1,1) is always treated as 1 |
| assertScore(1 * 1, bq.build()); |
| } |
| |
| public void testMinShouldMatchn2TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(2f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf2() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(2f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf2Missing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(2f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf3() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf3MissingOne() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf3MissingTwo() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Y"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf3() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf3Missing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf4() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(4f + 1), bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf4Missing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(4f + 1), bq.build()); |
| } |
| |
| // minShouldMatch with coord disabled |
| |
| public void testMinShouldMatch1TermMatchesCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMinShouldMatch2TermMatchesCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf2CoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf2MissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf3CoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf3MissingOneCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMinShouldMatch1OutOf3MissingTwoCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Y"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf3CoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf3MissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf4CoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMinShouldMatch2OutOf4MissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.SHOULD); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| // conjunctions |
| |
| public void testConjunction1TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| // LUCENE-4300: coord(1,1) is always treated as 1 |
| assertScore(1 * 1, bq.build()); |
| } |
| |
| public void testConjunction1TermMatches1Prohib() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.MUST_NOT); |
| // LUCENE-4300: coord(1,1) is always treated as 1 |
| assertScore(1 * 1, bq.build()); |
| } |
| |
| public void testConjunction1TermMatches2Prohib() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.MUST_NOT); |
| bq.add(term("2"), BooleanClause.Occur.MUST_NOT); |
| // LUCENE-4300: coord(1,1) is always treated as 1 |
| assertScore(1 * 1, bq.build()); |
| } |
| |
| public void testConjunction2TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.MUST); |
| assertScore(2 * 2/(2f + 1), bq.build()); |
| } |
| |
| public void testConjunction3TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.MUST); |
| bq.add(term("C"), BooleanClause.Occur.MUST); |
| assertScore(3 * 3/(3f + 1), bq.build()); |
| } |
| |
| // conjunctions coord disabled |
| |
| public void testConjunction1TermMatchesCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testConjunction1TermMatches1ProhibCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.MUST_NOT); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testConjunction1TermMatches2ProhibCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.MUST_NOT); |
| bq.add(term("2"), BooleanClause.Occur.MUST_NOT); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testConjunction2TermMatchesCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.MUST); |
| assertScore(2, bq.build()); |
| } |
| |
| // optional + mandatory mix |
| public void testMix2TermMatches() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(2f + 1), bq.build()); |
| } |
| |
| public void testMixMatch1OutOfTwo() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(2f + 1), bq.build()); |
| } |
| |
| public void testMixMatch1OutOfTwoMissing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(2f + 1), bq.build()); |
| } |
| |
| public void testMixMatch1OutOfThree() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testMixMatch1OutOfThreeOneMissing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testMixMatch2OutOfThree() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| public void testMixMatch2OutOfThreeMissing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| public void testMix2TermMatchesCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMixMatch1OutOfTwoCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMixMatch1OutOfTwoMissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMixMatch1OutOfThreeCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("2"), BooleanClause.Occur.SHOULD); |
| assertScore(1, bq.build()); |
| } |
| |
| public void testMixMatch1OutOfThreeOneMissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(1 * 1/(3f + 1), bq.build()); |
| } |
| |
| public void testMixMatch2OutOfThreeCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMixMatch2OutOfThreeMissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| // min should match + mandatory mix |
| |
| public void testMixMinShouldMatch2OutOfThree() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| public void testMixMinShouldMatch2OutOfThreeMissing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2 * 2/(3f + 1), bq.build()); |
| } |
| |
| public void testMixMinShouldMatch3OutOfFour() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("C"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(3 * 3/(4f + 1), bq.build()); |
| } |
| |
| public void testMixMinShouldMatch3OutOfFourMissing() throws Exception { |
| BooleanQuery.Builder bq = new BooleanQuery.Builder(); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("C"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(3 * 3/(4f + 1), bq.build()); |
| } |
| |
| public void testMixMinShouldMatch2OutOfThreeCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMixMinShouldMatch2OutOfThreeMissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(1); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(2, bq.build()); |
| } |
| |
| public void testMixMinShouldMatch3OutOfFourCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("C"), BooleanClause.Occur.SHOULD); |
| bq.add(term("1"), BooleanClause.Occur.SHOULD); |
| assertScore(3, bq.build()); |
| } |
| |
| public void testMixMinShouldMatch3OutOfFourMissingCoordDisabled() throws Exception { |
| BooleanQuery.Builder bq =new BooleanQuery.Builder(); |
| bq.setDisableCoord(true); |
| bq.setMinimumNumberShouldMatch(2); |
| bq.add(term("A"), BooleanClause.Occur.MUST); |
| bq.add(term("B"), BooleanClause.Occur.SHOULD); |
| bq.add(term("C"), BooleanClause.Occur.SHOULD); |
| bq.add(term("Z"), BooleanClause.Occur.SHOULD); |
| assertScore(3, bq.build()); |
| } |
| |
| // nested cases, make sure conjunctions propagate scoring |
| |
| public void testConjunctionNested() throws Exception { |
| BooleanQuery.Builder inner = new BooleanQuery.Builder(); |
| inner.add(term("A"), BooleanClause.Occur.MUST); |
| inner.add(term("B"), BooleanClause.Occur.MUST); |
| BooleanQuery.Builder outer = new BooleanQuery.Builder(); |
| outer.add(inner.build(), BooleanClause.Occur.MUST); |
| outer.add(term("C"), BooleanClause.Occur.MUST); |
| float innerScore = (1 + 1) * 2/(2f+1); |
| float outerScore = (innerScore + 1) * 2/(2f+1); |
| assertScore(outerScore, outer.build()); |
| } |
| |
| public void testConjunctionNestedOuterCoordDisabled() throws Exception { |
| BooleanQuery.Builder inner = new BooleanQuery.Builder(); |
| inner.add(term("A"), BooleanClause.Occur.MUST); |
| inner.add(term("B"), BooleanClause.Occur.MUST); |
| BooleanQuery.Builder outer = new BooleanQuery.Builder(); |
| outer.setDisableCoord(true); |
| outer.add(inner.build(), BooleanClause.Occur.MUST); |
| outer.add(term("C"), BooleanClause.Occur.MUST); |
| float innerScore = (1 + 1) * 2/(2f+1); |
| float outerScore = (innerScore + 1); |
| assertScore(outerScore, outer.build()); |
| } |
| |
| public void testConjunctionNestedInnerCoordDisabled() throws Exception { |
| BooleanQuery.Builder inner = new BooleanQuery.Builder(); |
| inner.setDisableCoord(true); |
| inner.add(term("A"), BooleanClause.Occur.MUST); |
| inner.add(term("B"), BooleanClause.Occur.MUST); |
| BooleanQuery.Builder outer = new BooleanQuery.Builder(); |
| outer.add(inner.build(), BooleanClause.Occur.MUST); |
| outer.add(term("C"), BooleanClause.Occur.MUST); |
| float innerScore = (1 + 1); |
| float outerScore = (innerScore + 1) * 2/(2f+1); |
| assertScore(outerScore, outer.build()); |
| } |
| |
| public void testConjunctionNestedCoordDisabledEverywhere() throws Exception { |
| BooleanQuery.Builder inner = new BooleanQuery.Builder(); |
| inner.setDisableCoord(true); |
| inner.add(term("A"), BooleanClause.Occur.MUST); |
| inner.add(term("B"), BooleanClause.Occur.MUST); |
| BooleanQuery.Builder outer = new BooleanQuery.Builder(); |
| outer.setDisableCoord(true); |
| outer.add(inner.build(), BooleanClause.Occur.MUST); |
| outer.add(term("C"), BooleanClause.Occur.MUST); |
| float innerScore = (1 + 1); |
| float outerScore = (innerScore + 1); |
| assertScore(outerScore, outer.build()); |
| } |
| |
| public void testConjunctionNestedSingle() throws Exception { |
| BooleanQuery.Builder inner = new BooleanQuery.Builder(); |
| inner.add(term("A"), BooleanClause.Occur.MUST); |
| inner.add(term("B"), BooleanClause.Occur.MUST); |
| BooleanQuery.Builder outer = new BooleanQuery.Builder(); |
| outer.add(inner.build(), BooleanClause.Occur.MUST); |
| float innerScore = (1 + 1) * 2/(2f+1); |
| // LUCENE-4300: coord(1,1) is always treated as 1 |
| float outerScore = innerScore * 1; |
| assertScore(outerScore, outer.build()); |
| } |
| |
| /** asserts score for our single matching good doc */ |
| private void assertScore(final float expected, Query query) throws Exception { |
| // test in-order |
| Weight weight = searcher.createNormalizedWeight(query, true); |
| Scorer scorer = weight.scorer(reader.leaves().get(0)); |
| assertTrue(scorer.docID() == -1 || scorer.docID() == DocIdSetIterator.NO_MORE_DOCS); |
| assertEquals(0, scorer.nextDoc()); |
| assertEquals(expected, scorer.score(), 0.0001f); |
| |
| // test bulk scorer |
| final AtomicBoolean seen = new AtomicBoolean(false); |
| BulkScorer bulkScorer = weight.bulkScorer(reader.leaves().get(0)); |
| assertNotNull(bulkScorer); |
| bulkScorer.score(new LeafCollector() { |
| Scorer scorer; |
| |
| @Override |
| public void setScorer(Scorer scorer) throws IOException { |
| this.scorer = scorer; |
| } |
| |
| @Override |
| public void collect(int doc) throws IOException { |
| assertFalse(seen.get()); |
| assertEquals(0, doc); |
| assertEquals(expected, scorer.score(), 0.0001f); |
| seen.set(true); |
| } |
| }, null, 0, 1); |
| assertTrue(seen.get()); |
| |
| // test the explanation |
| Explanation expl = weight.explain(reader.leaves().get(0), 0); |
| assertEquals(expected, expl.getValue(), 0.0001f); |
| } |
| |
| private Query term(String s) { |
| return new TermQuery(new Term("field", s)); |
| } |
| } |