blob: 984905c410414cbde9f9046657a1e563b9e139dd [file] [log] [blame]
Index: src/java/org/apache/lucene/search/BooleanScorer2.java
===================================================================
--- src/java/org/apache/lucene/search/BooleanScorer2.java (revision 293416)
+++ src/java/org/apache/lucene/search/BooleanScorer2.java (working copy)
@@ -37,6 +37,27 @@
private float[] coordFactors = null;
void init() { // use after all scorers have been added.
+
+ /* first thing first: if minNrShouldMatch, then we need to rollup
+ * the optional scorers and make the new scorer required.
+ */
+ if (0 < minNrShouldMatch) {
+ if (1 < optionalScorers.size()) {
+ requiredScorers.add(countingDisjunctionSumScorer(optionalScorers,
+ minNrShouldMatch));
+ maxCoord++;
+ optionalScorers = new ArrayList();
+ } else if (1 == optionalScorers.size() && 1 == minNrShouldMatch) {
+ requiredScorers.add(optionalScorers.get(0));
+ maxCoord++;
+ optionalScorers = new ArrayList();
+ } else {
+ /* remaining situations don't allow for any matches. */
+ requiredScorers.add(new NonMatchingScorer());
+ maxCoord++;
+ }
+ }
+
coordFactors = new float[maxCoord + 1];
Similarity sim = getSimilarity();
for (int i = 0; i <= maxCoord; i++) {
@@ -62,10 +83,17 @@
*/
private Scorer countingSumScorer = null;
- public BooleanScorer2(Similarity similarity) {
+ /** The number of optionalScorers that need to match (if there are any) */
+ private int minNrShouldMatch = 0;
+
+ public BooleanScorer2(Similarity similarity, int minNrShouldMatch) {
super(similarity);
coordinator = new Coordinator();
+ this.minNrShouldMatch = minNrShouldMatch;
}
+ public BooleanScorer2(Similarity similarity) {
+ this(similarity, 0);
+ }
public void add(final Scorer scorer, boolean required, boolean prohibited) {
if (!prohibited) {
@@ -126,10 +154,11 @@
}
}
- private Scorer countingDisjunctionSumScorer(List scorers)
+ private Scorer countingDisjunctionSumScorer(List scorers,
+ int minMrShouldMatch)
// each scorer from the list counted as a single matcher
{
- return new DisjunctionSumScorer(scorers) {
+ return new DisjunctionSumScorer(scorers, minMrShouldMatch) {
private int lastScoredDoc = -1;
public float score() throws IOException {
if (doc() > lastScoredDoc) {
@@ -184,7 +213,7 @@
new ArrayList()); // no optional scorers left
} else { // more than 1 optionalScorers, no required scorers
return makeCountingSumScorer2( // at least one optional scorer is required
- countingDisjunctionSumScorer(optionalScorers),
+ countingDisjunctionSumScorer(optionalScorers, 1),
new ArrayList()); // no optional scorers left
}
} else if (requiredScorers.size() == 1) { // 1 required
@@ -226,7 +255,7 @@
} else { // more optional
return makeCountingSumScorer3(
requiredCountingSumScorer,
- countingDisjunctionSumScorer(optionalScorers));
+ countingDisjunctionSumScorer(optionalScorers,1));
}
}
Index: src/java/org/apache/lucene/search/BooleanQuery.java
===================================================================
--- src/java/org/apache/lucene/search/BooleanQuery.java (revision 293416)
+++ src/java/org/apache/lucene/search/BooleanQuery.java (working copy)
@@ -104,6 +104,34 @@
return result;
}
+ /**
+ * Specifies a minimum number of the optional BooleanClauses
+ * which must be satisifed.
+ *
+ * <p>
+ * By default no optional clauses are neccessary for a match
+ * (unless there are no required clauses). If this method is used,
+ * then the specified numebr of clauses is required.
+ * </p>
+ * <p>
+ * Use of this method is totally independant of specifying that
+ * any specific clauses are required (or prohibited). This number will
+ * only be compared against the number of matching optional clauses.
+ * </p>
+ * <p>
+ * EXPERT NOTE: Using this method will force the use of BooleanWeight2,
+ * regardless of wether setUseScorer14(true) has been called.
+ * </p>
+ *
+ * @param min the number of optional clauses that must match
+ * @see #setUseScorer14
+ */
+ public void setMinimumNumberShouldMatch(int min) {
+ this.minNrShouldMatch = min;
+ }
+ protected int minNrShouldMatch = 0;
+
+
/** Adds a clause to a boolean query. Clauses may be:
* <ul>
* <li><code>required</code> which means that documents which <i>do not</i>
@@ -296,7 +324,8 @@
* and scores documents in document number order.
*/
public Scorer scorer(IndexReader reader) throws IOException {
- BooleanScorer2 result = new BooleanScorer2(similarity);
+ BooleanScorer2 result = new BooleanScorer2(similarity,
+ minNrShouldMatch);
for (int i = 0 ; i < weights.size(); i++) {
BooleanClause c = (BooleanClause)clauses.elementAt(i);
@@ -324,6 +353,12 @@
}
protected Weight createWeight(Searcher searcher) throws IOException {
+
+ if (0 < minNrShouldMatch) {
+ // :TODO: should we throw an exception if getUseScorer14 ?
+ return new BooleanWeight2(searcher);
+ }
+
return getUseScorer14() ? (Weight) new BooleanWeight(searcher)
: (Weight) new BooleanWeight2(searcher);
}