2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 using IndexReader = Mono.Lucene.Net.Index.IndexReader;
21 using ToStringUtils = Mono.Lucene.Net.Util.ToStringUtils;
23 namespace Mono.Lucene.Net.Search
27 /// <summary> A query that applies a filter to the results of another query.
29 /// <p/>Note: the bits are retrieved from the filter each time this
30 /// query is used in a search - use a CachingWrapperFilter to avoid
31 /// regenerating the bits every time.
33 /// <p/>Created: Apr 20, 2004 8:58:29 AM
38 /// <version> $Id: FilteredQuery.java 807821 2009-08-25 21:55:49Z mikemccand $
40 /// <seealso cref="CachingWrapperFilter">
43 public class FilteredQuery:Query
46 private class AnonymousClassWeight:Weight
48 public AnonymousClassWeight(Mono.Lucene.Net.Search.Weight weight, Mono.Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
50 InitBlock(weight, similarity, enclosingInstance);
52 private class AnonymousClassScorer:Scorer
54 private void InitBlock(Mono.Lucene.Net.Search.Scorer scorer, Mono.Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance)
57 this.docIdSetIterator = docIdSetIterator;
58 this.enclosingInstance = enclosingInstance;
60 private Mono.Lucene.Net.Search.Scorer scorer;
61 private Mono.Lucene.Net.Search.DocIdSetIterator docIdSetIterator;
62 private AnonymousClassWeight enclosingInstance;
63 public AnonymousClassWeight Enclosing_Instance
67 return enclosingInstance;
71 internal AnonymousClassScorer(Mono.Lucene.Net.Search.Scorer scorer, Mono.Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance, Mono.Lucene.Net.Search.Similarity Param1):base(Param1)
73 InitBlock(scorer, docIdSetIterator, enclosingInstance);
76 private int doc = - 1;
78 private int AdvanceToCommon(int scorerDoc, int disiDoc)
80 while (scorerDoc != disiDoc)
82 if (scorerDoc < disiDoc)
84 scorerDoc = scorer.Advance(disiDoc);
88 disiDoc = docIdSetIterator.Advance(scorerDoc);
94 /// <deprecated> use {@link #NextDoc()} instead.
96 [Obsolete("use NextDoc() instead. ")]
97 public override bool Next()
99 return NextDoc() != NO_MORE_DOCS;
102 public override int NextDoc()
104 int scorerDoc, disiDoc;
105 return doc = (disiDoc = docIdSetIterator.NextDoc()) != NO_MORE_DOCS && (scorerDoc = scorer.NextDoc()) != NO_MORE_DOCS && AdvanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS?scorer.DocID():NO_MORE_DOCS;
108 /// <deprecated> use {@link #DocID()} instead.
110 [Obsolete("use DocID() instead.")]
111 public override int Doc()
115 public override int DocID()
120 /// <deprecated> use {@link #Advance(int)} instead.
122 [Obsolete("use Advance(int) instead.")]
123 public override bool SkipTo(int i)
125 return Advance(i) != NO_MORE_DOCS;
128 public override int Advance(int target)
130 int disiDoc, scorerDoc;
131 return doc = (disiDoc = docIdSetIterator.Advance(target)) != NO_MORE_DOCS && (scorerDoc = scorer.Advance(disiDoc)) != NO_MORE_DOCS && AdvanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS?scorer.DocID():NO_MORE_DOCS;
134 public override float Score()
136 return Enclosing_Instance.Enclosing_Instance.GetBoost() * scorer.Score();
139 // add an explanation about whether the document was filtered
140 public override Explanation Explain(int i)
142 Explanation exp = scorer.Explain(i);
144 if (docIdSetIterator.Advance(i) == i)
146 exp.SetDescription("allowed by filter: " + exp.GetDescription());
147 exp.SetValue(Enclosing_Instance.Enclosing_Instance.GetBoost() * exp.GetValue());
151 exp.SetDescription("removed by filter: " + exp.GetDescription());
157 private void InitBlock(Mono.Lucene.Net.Search.Weight weight, Mono.Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
159 this.weight = weight;
160 this.similarity = similarity;
161 this.enclosingInstance = enclosingInstance;
163 private Mono.Lucene.Net.Search.Weight weight;
164 private Mono.Lucene.Net.Search.Similarity similarity;
165 private FilteredQuery enclosingInstance;
166 public FilteredQuery Enclosing_Instance
170 return enclosingInstance;
174 private float value_Renamed;
176 // pass these methods through to enclosed query's weight
177 public override float GetValue()
179 return value_Renamed;
181 public override float SumOfSquaredWeights()
183 return weight.SumOfSquaredWeights() * Enclosing_Instance.GetBoost() * Enclosing_Instance.GetBoost();
185 public override void Normalize(float v)
188 value_Renamed = weight.GetValue() * Enclosing_Instance.GetBoost();
190 public override Explanation Explain(IndexReader ir, int i)
192 Explanation inner = weight.Explain(ir, i);
193 if (Enclosing_Instance.GetBoost() != 1)
195 Explanation preBoost = inner;
196 inner = new Explanation(inner.GetValue() * Enclosing_Instance.GetBoost(), "product of:");
197 inner.AddDetail(new Explanation(Enclosing_Instance.GetBoost(), "boost"));
198 inner.AddDetail(preBoost);
200 Filter f = Enclosing_Instance.filter;
201 DocIdSet docIdSet = f.GetDocIdSet(ir);
202 DocIdSetIterator docIdSetIterator = docIdSet == null?DocIdSet.EMPTY_DOCIDSET.Iterator():docIdSet.Iterator();
203 if (docIdSetIterator == null)
205 docIdSetIterator = DocIdSet.EMPTY_DOCIDSET.Iterator();
207 if (docIdSetIterator.Advance(i) == i)
213 Explanation result = new Explanation(0.0f, "failure to match filter: " + f.ToString());
214 result.AddDetail(inner);
220 public override Query GetQuery()
222 return Enclosing_Instance;
225 // return a filtering scorer
226 public override Scorer Scorer(IndexReader indexReader, bool scoreDocsInOrder, bool topScorer)
228 Scorer scorer = weight.Scorer(indexReader, true, false);
233 DocIdSet docIdSet = Enclosing_Instance.filter.GetDocIdSet(indexReader);
234 if (docIdSet == null)
238 DocIdSetIterator docIdSetIterator = docIdSet.Iterator();
239 if (docIdSetIterator == null)
244 return new AnonymousClassScorer(scorer, docIdSetIterator, this, similarity);
248 internal Query query;
249 internal Filter filter;
251 /// <summary> Constructs a new query which applies a filter to the results of the original query.
252 /// Filter.getDocIdSet() will be called every time this query is used in a search.
254 /// <param name="query"> Query to be filtered, cannot be <code>null</code>.
256 /// <param name="filter">Filter to apply to query results, cannot be <code>null</code>.
258 public FilteredQuery(Query query, Filter filter)
261 this.filter = filter;
264 /// <summary> Returns a Weight that applies the filter to the enclosed query's Weight.
265 /// This is accomplished by overriding the Scorer returned by the Weight.
267 public override Weight CreateWeight(Searcher searcher)
269 Weight weight = query.CreateWeight(searcher);
270 Similarity similarity = query.GetSimilarity(searcher);
271 return new AnonymousClassWeight(weight, similarity, this);
274 /// <summary>Rewrites the wrapped query. </summary>
275 public override Query Rewrite(IndexReader reader)
277 Query rewritten = query.Rewrite(reader);
278 if (rewritten != query)
280 FilteredQuery clone = (FilteredQuery) this.Clone();
281 clone.query = rewritten;
290 public virtual Query GetQuery()
295 public virtual Filter GetFilter()
301 public override void ExtractTerms(System.Collections.Hashtable terms)
303 GetQuery().ExtractTerms(terms);
306 /// <summary>Prints a user-readable version of this query. </summary>
307 public override System.String ToString(System.String s)
309 System.Text.StringBuilder buffer = new System.Text.StringBuilder();
310 buffer.Append("filtered(");
311 buffer.Append(query.ToString(s));
312 buffer.Append(")->");
313 buffer.Append(filter);
314 buffer.Append(ToStringUtils.Boost(GetBoost()));
315 return buffer.ToString();
318 /// <summary>Returns true iff <code>o</code> is equal to this. </summary>
319 public override bool Equals(System.Object o)
321 if (o is FilteredQuery)
323 FilteredQuery fq = (FilteredQuery) o;
324 return (query.Equals(fq.query) && filter.Equals(fq.filter) && GetBoost() == fq.GetBoost());
329 /// <summary>Returns a hash code value for this object. </summary>
330 public override int GetHashCode()
332 return query.GetHashCode() ^ filter.GetHashCode() + System.Convert.ToInt32(GetBoost());