2 * Copyright 2004 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using Document
= Lucene
.Net
.Documents
.Document
;
19 using IndexReader
= Lucene
.Net
.Index
.IndexReader
;
20 using Term
= Lucene
.Net
.Index
.Term
;
21 using Directory
= Lucene
.Net
.Store
.Directory
;
23 namespace Lucene
.Net
.Search
26 /// <summary>Implements search over a single IndexReader.
28 /// <p>Applications usually need only call the inherited {@link #Search(Query)}
29 /// or {@link #Search(Query,Filter)} methods. For performance reasons it is
30 /// recommended to open only one IndexSearcher and use it for all of your searches.
32 /// <p>Note that you can only access Hits from an IndexSearcher as long as it is
33 /// not yet closed, otherwise an IOException will be thrown.
35 public class IndexSearcher
: Searcher
37 private class AnonymousClassHitCollector
: HitCollector
39 public AnonymousClassHitCollector(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.HitQueue hq
, int nDocs
, IndexSearcher enclosingInstance
)
41 InitBlock(bits
, totalHits
, hq
, nDocs
, enclosingInstance
);
43 private void InitBlock(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.HitQueue hq
, int nDocs
, IndexSearcher enclosingInstance
)
46 this.totalHits
= totalHits
;
49 this.enclosingInstance
= enclosingInstance
;
51 private System
.Collections
.BitArray bits
;
52 private int[] totalHits
;
53 private Lucene
.Net
.Search
.HitQueue hq
;
55 private IndexSearcher enclosingInstance
;
56 public IndexSearcher Enclosing_Instance
60 return enclosingInstance
;
64 private float minScore
= 0.0f
;
65 public override void Collect(int doc
, float score
)
67 if (score
> 0.0f
&& (bits
== null || bits
.Get(doc
)))
69 // skip docs not in bits
71 if (hq
.Size() < nDocs
|| score
>= minScore
)
73 hq
.Insert(new ScoreDoc(doc
, score
));
74 minScore
= ((ScoreDoc
) hq
.Top()).score
; // maintain minScore
79 private class AnonymousClassHitCollector1
: HitCollector
81 public AnonymousClassHitCollector1(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.FieldSortedHitQueue hq
, IndexSearcher enclosingInstance
)
83 InitBlock(bits
, totalHits
, hq
, enclosingInstance
);
85 private void InitBlock(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.FieldSortedHitQueue hq
, IndexSearcher enclosingInstance
)
88 this.totalHits
= totalHits
;
90 this.enclosingInstance
= enclosingInstance
;
92 private System
.Collections
.BitArray bits
;
93 private int[] totalHits
;
94 private Lucene
.Net
.Search
.FieldSortedHitQueue hq
;
95 private IndexSearcher enclosingInstance
;
96 public IndexSearcher Enclosing_Instance
100 return enclosingInstance
;
104 public override void Collect(int doc
, float score
)
106 if (score
> 0.0f
&& (bits
== null || bits
.Get(doc
)))
108 // skip docs not in bits
110 hq
.Insert(new FieldDoc(doc
, score
));
114 private class AnonymousClassHitCollector2
: HitCollector
116 public AnonymousClassHitCollector2(System
.Collections
.BitArray bits
, Lucene
.Net
.Search
.HitCollector results
, IndexSearcher enclosingInstance
)
118 InitBlock(bits
, results
, enclosingInstance
);
120 private void InitBlock(System
.Collections
.BitArray bits
, Lucene
.Net
.Search
.HitCollector results
, IndexSearcher enclosingInstance
)
123 this.results
= results
;
124 this.enclosingInstance
= enclosingInstance
;
126 private System
.Collections
.BitArray bits
;
127 private Lucene
.Net
.Search
.HitCollector results
;
128 private IndexSearcher enclosingInstance
;
129 public IndexSearcher Enclosing_Instance
133 return enclosingInstance
;
137 public override void Collect(int doc
, float score
)
141 // skip docs not in bits
142 results
.Collect(doc
, score
);
146 internal IndexReader reader
;
147 private bool closeReader
;
149 public IndexReader Reader
151 get { return reader; }
154 /// <summary>Creates a searcher searching the index in the named directory. </summary>
155 public IndexSearcher(System
.String path
) : this(IndexReader
.Open(path
), true)
159 /// <summary>Creates a searcher searching the index in the provided directory. </summary>
160 public IndexSearcher(Directory directory
) : this(IndexReader
.Open(directory
), true)
164 /// <summary>Creates a searcher searching the provided index. </summary>
165 public IndexSearcher(IndexReader r
) : this(r
, false)
169 private IndexSearcher(IndexReader r
, bool closeReader
)
172 this.closeReader
= closeReader
;
175 /// <summary>Return the {@link IndexReader} this searches. </summary>
176 public virtual IndexReader
GetIndexReader()
181 /// <summary> Note that the underlying IndexReader is not closed, if
182 /// IndexSearcher was constructed with IndexSearcher(IndexReader r).
183 /// If the IndexReader was supplied implicitly by specifying a directory, then
184 /// the IndexReader gets closed.
186 public override void Close()
193 public override int DocFreq(Term term
)
195 return reader
.DocFreq(term
);
199 public override Document
Doc(int i
)
201 return reader
.Document(i
);
205 public override int MaxDoc()
207 return reader
.MaxDoc();
211 public override TopDocs
Search(Weight weight
, Filter filter
, int nDocs
)
215 // null might be returned from hq.top() below.
216 throw new System
.ArgumentException("nDocs must be > 0");
218 Scorer scorer
= weight
.Scorer(reader
);
220 return new TopDocs(0, new ScoreDoc
[0], System
.Single
.NegativeInfinity
);
222 System
.Collections
.BitArray bits
= filter
!= null?filter
.Bits(reader
):null;
223 HitQueue hq
= new HitQueue(nDocs
);
224 int[] totalHits
= new int[1];
225 scorer
.Score(new AnonymousClassHitCollector(bits
, totalHits
, hq
, nDocs
, this));
227 ScoreDoc
[] scoreDocs
= new ScoreDoc
[hq
.Size()];
228 for (int i
= hq
.Size() - 1; i
>= 0; i
--)
230 scoreDocs
[i
] = (ScoreDoc
) hq
.Pop();
232 float maxScore
= (totalHits
[0] == 0) ? System
.Single
.NegativeInfinity
: scoreDocs
[0].score
;
234 return new TopDocs(totalHits
[0], scoreDocs
, maxScore
);
238 public override TopFieldDocs
Search(Weight weight
, Filter filter
, int nDocs
, Sort sort
)
240 Scorer scorer
= weight
.Scorer(reader
);
242 return new TopFieldDocs(0, new ScoreDoc
[0], sort
.fields
, System
.Single
.NegativeInfinity
);
244 System
.Collections
.BitArray bits
= filter
!= null ? filter
.Bits(reader
) : null;
245 FieldSortedHitQueue hq
= new FieldSortedHitQueue(reader
, sort
.fields
, nDocs
);
246 int[] totalHits
= new int[1];
247 scorer
.Score(new AnonymousClassHitCollector1(bits
, totalHits
, hq
, this));
249 ScoreDoc
[] scoreDocs
= new ScoreDoc
[hq
.Size()];
250 for (int i
= hq
.Size() - 1; i
>= 0; i
--)
252 scoreDocs
[i
] = hq
.FillFields((FieldDoc
) hq
.Pop());
254 return new TopFieldDocs(totalHits
[0], scoreDocs
, hq
.GetFields(), hq
.GetMaxScore());
258 public override void Search(Weight weight
, Filter filter
, HitCollector results
)
260 HitCollector collector
= results
;
263 System
.Collections
.BitArray bits
= filter
.Bits(reader
);
264 collector
= new AnonymousClassHitCollector2(bits
, results
, this);
267 Scorer scorer
= weight
.Scorer(reader
);
270 scorer
.Score(collector
);
273 public override Query
Rewrite(Query original
)
275 Query query
= original
;
276 for (Query rewrittenQuery
= query
.Rewrite(reader
); rewrittenQuery
!= query
; rewrittenQuery
= query
.Rewrite(reader
))
278 query
= rewrittenQuery
;
283 public override Explanation
Explain(Weight weight
, int doc
)
285 return weight
.Explain(reader
, doc
);