📄 booleanquery.java
字号:
package org.apache.lucene.search;/** * Copyright 2004 The Apache Software Foundation * * Licensed 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.Vector;import org.apache.lucene.index.IndexReader;/** A Query that matches documents matching boolean combinations of other queries, typically {@link TermQuery}s or {@link PhraseQuery}s. */public class BooleanQuery extends Query { /** * Default value is 1024. Use <code>org.apache.lucene.maxClauseCount</code> * system property to override. */ public static int maxClauseCount = Integer.parseInt(System.getProperty("org.apache.lucene.maxClauseCount", "1024")); /** Thrown when an attempt is made to add more than {@link * #getMaxClauseCount()} clauses. */ public static class TooManyClauses extends RuntimeException {} /** Return the maximum number of clauses permitted, 1024 by default. * Attempts to add more than the permitted number of clauses cause {@link * TooManyClauses} to be thrown.*/ public static int getMaxClauseCount() { return maxClauseCount; } /** Set the maximum number of clauses permitted. */ public static void setMaxClauseCount(int maxClauseCount) { BooleanQuery.maxClauseCount = maxClauseCount; } private Vector clauses = new Vector(); /** Constructs an empty boolean query. */ public BooleanQuery() {} /** Adds a clause to a boolean query. Clauses may be: * <ul> * <li><code>required</code> which means that documents which <i>do not</i> * match this sub-query will <i>not</i> match the boolean query; * <li><code>prohibited</code> which means that documents which <i>do</i> * match this sub-query will <i>not</i> match the boolean query; or * <li>neither, in which case matched documents are neither prohibited from * nor required to match the sub-query. However, a document must match at * least 1 sub-query to match the boolean query. * </ul> * It is an error to specify a clause as both <code>required</code> and * <code>prohibited</code>. * * @see #getMaxClauseCount() */ public void add(Query query, boolean required, boolean prohibited) { add(new BooleanClause(query, required, prohibited)); } /** Adds a clause to a boolean query. * @see #getMaxClauseCount() */ public void add(BooleanClause clause) { if (clauses.size() >= maxClauseCount) throw new TooManyClauses(); clauses.addElement(clause); } /** Returns the set of clauses in this query. */ public BooleanClause[] getClauses() { return (BooleanClause[])clauses.toArray(new BooleanClause[0]); } private class BooleanWeight implements Weight { private Searcher searcher; private Vector weights = new Vector(); public BooleanWeight(Searcher searcher) { this.searcher = searcher; for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); weights.add(c.query.createWeight(searcher)); } } public Query getQuery() { return BooleanQuery.this; } public float getValue() { return getBoost(); } public float sumOfSquaredWeights() throws IOException { float sum = 0.0f; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); if (!c.prohibited) sum += w.sumOfSquaredWeights(); // sum sub weights } sum *= getBoost() * getBoost(); // boost each sub-weight return sum ; } public void normalize(float norm) { norm *= getBoost(); // incorporate boost for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); if (!c.prohibited) w.normalize(norm); } } public Scorer scorer(IndexReader reader) throws IOException { // First see if the (faster) ConjunctionScorer will work. This can be // used when all clauses are required. Also, at this point a // BooleanScorer cannot be embedded in a ConjunctionScorer, as the hits // from a BooleanScorer are not always sorted by document number (sigh) // and hence BooleanScorer cannot implement skipTo() correctly, which is // required by ConjunctionScorer. boolean allRequired = true; boolean noneBoolean = true; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); if (!c.required) allRequired = false; if (c.query instanceof BooleanQuery) noneBoolean = false; } if (allRequired && noneBoolean) { // ConjunctionScorer is okay ConjunctionScorer result = new ConjunctionScorer(getSimilarity(searcher)); for (int i = 0 ; i < weights.size(); i++) { Weight w = (Weight)weights.elementAt(i); Scorer subScorer = w.scorer(reader); if (subScorer == null) return null; result.add(subScorer); } return result; } // Use good-old BooleanScorer instead. BooleanScorer result = new BooleanScorer(getSimilarity(searcher)); for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); Scorer subScorer = w.scorer(reader); if (subScorer != null) result.add(subScorer, c.required, c.prohibited); else if (c.required) return null; } return result; } public Explanation explain(IndexReader reader, int doc) throws IOException { Explanation sumExpl = new Explanation(); sumExpl.setDescription("sum of:"); int coord = 0; int maxCoord = 0; float sum = 0.0f; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); Explanation e = w.explain(reader, doc); if (!c.prohibited) maxCoord++; if (e.getValue() > 0) { if (!c.prohibited) { sumExpl.addDetail(e); sum += e.getValue(); coord++; } else { return new Explanation(0.0f, "match prohibited"); } } else if (c.required) { return new Explanation(0.0f, "match required"); } } sumExpl.setValue(sum); if (coord == 1) // only one clause matched sumExpl = sumExpl.getDetails()[0]; // eliminate wrapper float coordFactor = getSimilarity(searcher).coord(coord, maxCoord); if (coordFactor == 1.0f) // coord is no-op return sumExpl; // eliminate wrapper else { Explanation result = new Explanation(); result.setDescription("product of:"); result.addDetail(sumExpl); result.addDetail(new Explanation(coordFactor, "coord("+coord+"/"+maxCoord+")")); result.setValue(sum*coordFactor); return result; } } } protected Weight createWeight(Searcher searcher) { return new BooleanWeight(searcher); } public Query rewrite(IndexReader reader) throws IOException { if (clauses.size() == 1) { // optimize 1-clause queries BooleanClause c = (BooleanClause)clauses.elementAt(0); if (!c.prohibited) { // just return clause Query query = c.query.rewrite(reader); // rewrite first if (getBoost() != 1.0f) { // incorporate boost if (query == c.query) // if rewrite was no-op query = (Query)query.clone(); // then clone before boost query.setBoost(getBoost() * query.getBoost()); } return query; } } BooleanQuery clone = null; // recursively rewrite for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Query query = c.query.rewrite(reader); if (query != c.query) { // clause rewrote: must clone if (clone == null) clone = (BooleanQuery)this.clone(); clone.clauses.setElementAt (new BooleanClause(query, c.required, c.prohibited), i); } } if (clone != null) { return clone; // some clauses rewrote } else return this; // no clauses rewrote } public Object clone() { BooleanQuery clone = (BooleanQuery)super.clone(); clone.clauses = (Vector)this.clauses.clone(); return clone; } /** Prints a user-readable version of this query. */ public String toString(String field) { StringBuffer buffer = new StringBuffer(); if (getBoost() != 1.0) { buffer.append("("); } for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); if (c.prohibited) buffer.append("-"); else if (c.required) buffer.append("+"); Query subQuery = c.query; if (subQuery instanceof BooleanQuery) { // wrap sub-bools in parens buffer.append("("); buffer.append(c.query.toString(field)); buffer.append(")"); } else buffer.append(c.query.toString(field)); if (i != clauses.size()-1) buffer.append(" "); } if (getBoost() != 1.0) { buffer.append(")^"); buffer.append(getBoost()); } return buffer.toString(); } /** Returns true iff <code>o</code> is equal to this. */ public boolean equals(Object o) { if (!(o instanceof BooleanQuery)) return false; BooleanQuery other = (BooleanQuery)o; return (this.getBoost() == other.getBoost()) && this.clauses.equals(other.clauses); } /** Returns a hash code value for this object.*/ public int hashCode() { return Float.floatToIntBits(getBoost()) ^ clauses.hashCode(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -