Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
FilteredQuery.cs
Go to the documentation of this file.
1 /*
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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 
18 using System;
19 using Lucene.Net.Index;
20 using IndexReader = Lucene.Net.Index.IndexReader;
21 using ToStringUtils = Lucene.Net.Util.ToStringUtils;
22 
23 namespace Lucene.Net.Search
24 {
25 
26 
27  /// <summary> A query that applies a filter to the results of another query.
28  ///
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.
32  ///
33  /// <p/>Created: Apr 20, 2004 8:58:29 AM
34  ///
35  /// </summary>
36  /// <since>1.4</since>
37  /// <seealso cref="CachingWrapperFilter"/>
38  [Serializable]
39  public class FilteredQuery:Query
40  {
41  [Serializable]
42  private class AnonymousClassWeight:Weight
43  {
44  public AnonymousClassWeight(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
45  {
46  InitBlock(weight, similarity, enclosingInstance);
47  }
48  private class AnonymousClassScorer:Scorer
49  {
50  private void InitBlock(Lucene.Net.Search.Scorer scorer, Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance)
51  {
52  this.scorer = scorer;
53  this.docIdSetIterator = docIdSetIterator;
54  this.enclosingInstance = enclosingInstance;
55  }
56  private Lucene.Net.Search.Scorer scorer;
57  private Lucene.Net.Search.DocIdSetIterator docIdSetIterator;
58  private AnonymousClassWeight enclosingInstance;
59  public AnonymousClassWeight Enclosing_Instance
60  {
61  get
62  {
63  return enclosingInstance;
64  }
65 
66  }
67  internal AnonymousClassScorer(Lucene.Net.Search.Scorer scorer, Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance, Lucene.Net.Search.Similarity Param1):base(Param1)
68  {
69  InitBlock(scorer, docIdSetIterator, enclosingInstance);
70  }
71 
72  private int doc = - 1;
73 
74  private int AdvanceToCommon(int scorerDoc, int disiDoc)
75  {
76  while (scorerDoc != disiDoc)
77  {
78  if (scorerDoc < disiDoc)
79  {
80  scorerDoc = scorer.Advance(disiDoc);
81  }
82  else
83  {
84  disiDoc = docIdSetIterator.Advance(scorerDoc);
85  }
86  }
87  return scorerDoc;
88  }
89 
90  public override int NextDoc()
91  {
92  int scorerDoc, disiDoc;
93  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;
94  }
95  public override int DocID()
96  {
97  return doc;
98  }
99 
100  public override int Advance(int target)
101  {
102  int disiDoc, scorerDoc;
103  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;
104  }
105 
106  public override float Score()
107  {
108  return Enclosing_Instance.Enclosing_Instance.Boost * scorer.Score();
109  }
110  }
111  private void InitBlock(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
112  {
113  this.weight = weight;
114  this.similarity = similarity;
115  this.enclosingInstance = enclosingInstance;
116  }
117  private Lucene.Net.Search.Weight weight;
118  private Lucene.Net.Search.Similarity similarity;
119  private FilteredQuery enclosingInstance;
120  public FilteredQuery Enclosing_Instance
121  {
122  get
123  {
124  return enclosingInstance;
125  }
126 
127  }
128  private float value_Renamed;
129 
130  // pass these methods through to enclosed query's weight
131 
132  public override float Value
133  {
134  get { return value_Renamed; }
135  }
136 
137  public override float GetSumOfSquaredWeights()
138  {
139  return weight.GetSumOfSquaredWeights()*Enclosing_Instance.Boost*Enclosing_Instance.Boost;
140  }
141 
142  public override void Normalize(float v)
143  {
144  weight.Normalize(v);
145  value_Renamed = weight.Value * Enclosing_Instance.Boost;
146  }
147  public override Explanation Explain(IndexReader ir, int i)
148  {
149  Explanation inner = weight.Explain(ir, i);
150  if (Enclosing_Instance.Boost != 1)
151  {
152  Explanation preBoost = inner;
153  inner = new Explanation(inner.Value * Enclosing_Instance.Boost, "product of:");
154  inner.AddDetail(new Explanation(Enclosing_Instance.Boost, "boost"));
155  inner.AddDetail(preBoost);
156  }
157  Filter f = Enclosing_Instance.filter;
158  DocIdSet docIdSet = f.GetDocIdSet(ir);
159  DocIdSetIterator docIdSetIterator = docIdSet == null?DocIdSet.EMPTY_DOCIDSET.Iterator():docIdSet.Iterator();
160  if (docIdSetIterator == null)
161  {
162  docIdSetIterator = DocIdSet.EMPTY_DOCIDSET.Iterator();
163  }
164  if (docIdSetIterator.Advance(i) == i)
165  {
166  return inner;
167  }
168  else
169  {
170  Explanation result = new Explanation(0.0f, "failure to match filter: " + f.ToString());
171  result.AddDetail(inner);
172  return result;
173  }
174  }
175 
176  // return this query
177 
178  public override Query Query
179  {
180  get { return Enclosing_Instance; }
181  }
182 
183  // return a filtering scorer
184  public override Scorer Scorer(IndexReader indexReader, bool scoreDocsInOrder, bool topScorer)
185  {
186  Scorer scorer = weight.Scorer(indexReader, true, false);
187  if (scorer == null)
188  {
189  return null;
190  }
191  DocIdSet docIdSet = Enclosing_Instance.filter.GetDocIdSet(indexReader);
192  if (docIdSet == null)
193  {
194  return null;
195  }
196  DocIdSetIterator docIdSetIterator = docIdSet.Iterator();
197  if (docIdSetIterator == null)
198  {
199  return null;
200  }
201 
202  return new AnonymousClassScorer(scorer, docIdSetIterator, this, similarity);
203  }
204  }
205 
206  internal Query query;
207  internal Filter filter;
208 
209  /// <summary> Constructs a new query which applies a filter to the results of the original query.
210  /// Filter.getDocIdSet() will be called every time this query is used in a search.
211  /// </summary>
212  /// <param name="query"> Query to be filtered, cannot be <c>null</c>.
213  /// </param>
214  /// <param name="filter">Filter to apply to query results, cannot be <c>null</c>.
215  /// </param>
216  public FilteredQuery(Query query, Filter filter)
217  {
218  this.query = query;
219  this.filter = filter;
220  }
221 
222  /// <summary> Returns a Weight that applies the filter to the enclosed query's Weight.
223  /// This is accomplished by overriding the Scorer returned by the Weight.
224  /// </summary>
225  public override Weight CreateWeight(Searcher searcher)
226  {
227  Weight weight = query.CreateWeight(searcher);
228  Similarity similarity = query.GetSimilarity(searcher);
229  return new AnonymousClassWeight(weight, similarity, this);
230  }
231 
232  /// <summary>Rewrites the wrapped query. </summary>
233  public override Query Rewrite(IndexReader reader)
234  {
235  Query rewritten = query.Rewrite(reader);
236  if (rewritten != query)
237  {
238  FilteredQuery clone = (FilteredQuery) this.Clone();
239  clone.query = rewritten;
240  return clone;
241  }
242  else
243  {
244  return this;
245  }
246  }
247 
248  public virtual Query Query
249  {
250  get { return query; }
251  }
252 
253  public virtual Filter Filter
254  {
255  get { return filter; }
256  }
257 
258  // inherit javadoc
259  public override void ExtractTerms(System.Collections.Generic.ISet<Term> terms)
260  {
261  Query.ExtractTerms(terms);
262  }
263 
264  /// <summary>Prints a user-readable version of this query. </summary>
265  public override System.String ToString(System.String s)
266  {
267  System.Text.StringBuilder buffer = new System.Text.StringBuilder();
268  buffer.Append("filtered(");
269  buffer.Append(query.ToString(s));
270  buffer.Append(")->");
271  buffer.Append(filter);
272  buffer.Append(ToStringUtils.Boost(Boost));
273  return buffer.ToString();
274  }
275 
276  /// <summary>Returns true iff <c>o</c> is equal to this. </summary>
277  public override bool Equals(System.Object o)
278  {
279  if (o is FilteredQuery)
280  {
281  FilteredQuery fq = (FilteredQuery) o;
282  return (query.Equals(fq.query) && filter.Equals(fq.filter) && Boost == fq.Boost);
283  }
284  return false;
285  }
286 
287  /// <summary>Returns a hash code value for this object. </summary>
288  public override int GetHashCode()
289  {
290  return query.GetHashCode() ^ filter.GetHashCode() + System.Convert.ToInt32(Boost);
291  }
292  }
293 }