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.
17 using Document
= Lucene
.Net
.Documents
.Document
;
18 using IndexReader
= Lucene
.Net
.Index
.IndexReader
;
19 using Term
= Lucene
.Net
.Index
.Term
;
20 using Directory
= Lucene
.Net
.Store
.Directory
;
21 namespace Lucene
.Net
.Search
24 /// <summary>Implements search over a single IndexReader.
26 /// <p>Applications usually need only call the inherited {@link #Search(Query)}
27 /// or {@link #Search(Query,Filter)} methods. For performance reasons it is
28 /// recommended to open only one IndexSearcher and use it for all of your searches.
30 public class IndexSearcher
: Searcher
32 private class AnonymousClassHitCollector
: HitCollector
34 public AnonymousClassHitCollector(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.HitQueue hq
, int nDocs
, IndexSearcher enclosingInstance
)
36 InitBlock(bits
, totalHits
, hq
, nDocs
, enclosingInstance
);
38 private void InitBlock(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.HitQueue hq
, int nDocs
, IndexSearcher enclosingInstance
)
41 this.totalHits
= totalHits
;
44 this.enclosingInstance
= enclosingInstance
;
46 private System
.Collections
.BitArray bits
;
47 private int[] totalHits
;
48 private Lucene
.Net
.Search
.HitQueue hq
;
50 private IndexSearcher enclosingInstance
;
51 public IndexSearcher Enclosing_Instance
55 return enclosingInstance
;
59 private float minScore
= 0.0f
;
60 public override void Collect(int doc
, float score
)
62 if (score
> 0.0f
&& (bits
== null || bits
.Get(doc
)))
64 // skip docs not in bits
66 if (hq
.Size() < nDocs
|| score
>= minScore
)
68 hq
.Insert(new ScoreDoc(doc
, score
));
69 minScore
= ((ScoreDoc
) hq
.Top()).score
; // maintain minScore
74 private class AnonymousClassHitCollector1
: HitCollector
76 public AnonymousClassHitCollector1(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.FieldSortedHitQueue hq
, IndexSearcher enclosingInstance
)
78 InitBlock(bits
, totalHits
, hq
, enclosingInstance
);
80 private void InitBlock(System
.Collections
.BitArray bits
, int[] totalHits
, Lucene
.Net
.Search
.FieldSortedHitQueue hq
, IndexSearcher enclosingInstance
)
83 this.totalHits
= totalHits
;
85 this.enclosingInstance
= enclosingInstance
;
87 private System
.Collections
.BitArray bits
;
88 private int[] totalHits
;
89 private Lucene
.Net
.Search
.FieldSortedHitQueue hq
;
90 private IndexSearcher enclosingInstance
;
91 public IndexSearcher Enclosing_Instance
95 return enclosingInstance
;
99 public override void Collect(int doc
, float score
)
101 if (score
> 0.0f
&& (bits
== null || bits
.Get(doc
)))
103 // skip docs not in bits
105 hq
.Insert(new FieldDoc(doc
, score
));
109 private class AnonymousClassHitCollector2
: HitCollector
111 public AnonymousClassHitCollector2(System
.Collections
.BitArray bits
, Lucene
.Net
.Search
.HitCollector results
, IndexSearcher enclosingInstance
)
113 InitBlock(bits
, results
, enclosingInstance
);
115 private void InitBlock(System
.Collections
.BitArray bits
, Lucene
.Net
.Search
.HitCollector results
, IndexSearcher enclosingInstance
)
118 this.results
= results
;
119 this.enclosingInstance
= enclosingInstance
;
121 private System
.Collections
.BitArray bits
;
122 private Lucene
.Net
.Search
.HitCollector results
;
123 private IndexSearcher enclosingInstance
;
124 public IndexSearcher Enclosing_Instance
128 return enclosingInstance
;
132 public override void Collect(int doc
, float score
)
136 // skip docs not in bits
137 results
.Collect(doc
, score
);
141 public /*internal*/ IndexReader reader
;
142 private bool closeReader
;
144 /// <summary>Creates a searcher searching the index in the named directory. </summary>
145 public IndexSearcher(System
.String path
) : this(IndexReader
.Open(path
), true)
149 /// <summary>Creates a searcher searching the index in the provided directory. </summary>
150 public IndexSearcher(Directory directory
) : this(IndexReader
.Open(directory
), true)
154 /// <summary>Creates a searcher searching the provided index. </summary>
155 public IndexSearcher(IndexReader r
) : this(r
, false)
159 private IndexSearcher(IndexReader r
, bool closeReader
)
162 this.closeReader
= closeReader
;
165 /// <summary>Return the {@link IndexReader} this searches. </summary>
166 public virtual IndexReader
GetIndexReader()
171 /// <summary> Note that the underlying IndexReader is not closed, if
172 /// IndexSearcher was constructed with IndexSearcher(IndexReader r).
173 /// If the IndexReader was supplied implicitly by specifying a directory, then
174 /// the IndexReader gets closed.
176 public override void Close()
183 public override int DocFreq(Term term
)
185 return reader
.DocFreq(term
);
189 public override Document
Doc(int i
)
191 return reader
.Document(i
);
195 public override int MaxDoc()
197 return reader
.MaxDoc();
201 public override TopDocs
Search(Query query
, Filter filter
, int nDocs
)
203 return Search(query
.Weight(this), filter
, nDocs
);
207 public override TopDocs
Search(Weight weight
, Filter filter
, int nDocs
)
211 // null might be returned from hq.top() below.
212 throw new System
.ArgumentException("nDocs must be > 0");
214 Scorer scorer
= weight
.Scorer(reader
);
216 return new TopDocs(0, new ScoreDoc
[0]);
218 System
.Collections
.BitArray bits
= filter
!= null?filter
.Bits(reader
):null;
219 HitQueue hq
= new HitQueue(nDocs
);
220 int[] totalHits
= new int[1];
221 scorer
.Score(new AnonymousClassHitCollector(bits
, totalHits
, hq
, nDocs
, this));
223 ScoreDoc
[] scoreDocs
= new ScoreDoc
[hq
.Size()];
224 for (int i
= hq
.Size() - 1; i
>= 0; i
--)
226 scoreDocs
[i
] = (ScoreDoc
) hq
.Pop();
228 return new TopDocs(totalHits
[0], scoreDocs
);
232 public override TopFieldDocs
Search(Query query
, Filter filter
, int nDocs
, Sort sort
)
234 return Search(query
.Weight(this), filter
, nDocs
, sort
);
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
);
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());
259 public override void Search(Query query
, Filter filter
, HitCollector results
)
261 Search(query
.Weight(this), filter
, results
);
265 public override void Search(Weight weight
, Filter filter
, HitCollector results
)
267 HitCollector collector
= results
;
270 System
.Collections
.BitArray bits
= filter
.Bits(reader
);
271 collector
= new AnonymousClassHitCollector2(bits
, results
, this);
274 Scorer scorer
= weight
.Scorer(reader
);
277 scorer
.Score(collector
);
280 public override Query
Rewrite(Query original
)
282 Query query
= original
;
283 for (Query rewrittenQuery
= query
.Rewrite(reader
); rewrittenQuery
!= query
; rewrittenQuery
= query
.Rewrite(reader
))
285 query
= rewrittenQuery
;
290 public override Explanation
Explain(Query query
, int doc
)
292 return Explain(query
.Weight(this), doc
);
295 public override Explanation
Explain(Weight weight
, int doc
)
297 return weight
.Explain(reader
, doc
);