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
;
20 namespace Lucene
.Net
.Search
23 /// <summary>A ranked list of documents, used to hold search results. </summary>
24 public sealed class Hits
26 private Weight weight
;
27 private Searcher searcher
;
28 private Filter filter
= null;
29 private Sort sort
= null;
31 private int length
; // the total number of hits
32 private System
.Collections
.ArrayList hitDocs
= System
.Collections
.ArrayList
.Synchronized(new System
.Collections
.ArrayList(10)); // cache of hits retrieved
34 private HitDoc first
; // head of LRU cache
35 private HitDoc last
; // tail of LRU cache
36 private int numDocs
= 0; // number cached
37 private int maxDocs
= 200; // max to cache
39 internal Hits(Searcher s
, Query q
, Filter f
)
44 GetMoreDocs(50); // retrieve 100 initially
47 internal Hits(Searcher s
, Query q
, Filter f
, Sort o
)
53 GetMoreDocs(50); // retrieve 100 initially
56 /// <summary> Tries to add new documents to hitDocs.
57 /// Ensures that the hit numbered <code>min</code> has been retrieved.
59 private void GetMoreDocs(int min
)
61 if (hitDocs
.Count
> min
)
66 int n
= min
* 2; // double # retrieved
67 TopDocs topDocs
= (sort
== null) ? searcher
.Search(weight
, filter
, n
) : searcher
.Search(weight
, filter
, n
, sort
);
68 length
= topDocs
.totalHits
;
69 ScoreDoc
[] scoreDocs
= topDocs
.scoreDocs
;
71 float scoreNorm
= 1.0f
;
73 if (length
> 0 && topDocs
.GetMaxScore() > 1.0f
)
75 scoreNorm
= 1.0f
/ topDocs
.GetMaxScore();
78 int end
= scoreDocs
.Length
< length
?scoreDocs
.Length
:length
;
79 for (int i
= hitDocs
.Count
; i
< end
; i
++)
81 hitDocs
.Add(new HitDoc(scoreDocs
[i
].score
* scoreNorm
, scoreDocs
[i
].doc
));
85 /// <summary>Returns the total number of hits available in this set. </summary>
91 /// <summary>Returns the stored fields of the n<sup>th</sup> document in this set.
92 /// <p>Documents are cached, so that repeated requests for the same element may
93 /// return the same Document object.
95 public Document
Doc(int n
)
97 HitDoc hitDoc
= HitDoc(n
);
99 // Update LRU cache of documents
100 Remove(hitDoc
); // remove from list, if there
101 AddToFront(hitDoc
); // add to front of list
102 if (numDocs
> maxDocs
)
105 HitDoc oldLast
= last
;
106 Remove(last
); // flush last
107 oldLast
.doc
= null; // let doc get gc'd
110 if (hitDoc
.doc
== null)
112 hitDoc
.doc
= searcher
.Doc(hitDoc
.id
); // cache miss: read document
118 /// <summary>Returns the score for the nth document in this set. </summary>
119 public float Score(int n
)
121 return HitDoc(n
).score
;
124 /// <summary>Returns the id for the nth document in this set. </summary>
130 /// <summary> Returns a {@link HitIterator} to navigate the Hits. Each item returned
131 /// from {@link Iterator#next()} is a {@link Hit}.
133 /// <b>Caution:</b> Iterate only over the hits needed. Iterating over all
134 /// hits is generally not desirable and may be the source of
135 /// performance issues.
138 public System
.Collections
.IEnumerator
Iterator()
140 return new HitIterator(this);
143 private HitDoc
HitDoc(int n
)
147 throw new System
.IndexOutOfRangeException("Not a valid hit number: " + n
);
150 if (n
>= hitDocs
.Count
)
155 return (HitDoc
) hitDocs
[n
];
158 private void AddToFront(HitDoc hitDoc
)
160 // insert at front of cache
177 private void Remove(HitDoc hitDoc
)
180 if (hitDoc
.doc
== null)
182 // it's not in the list
186 if (hitDoc
.next
== null)
192 hitDoc
.next
.prev
= hitDoc
.prev
;
195 if (hitDoc
.prev
== null)
201 hitDoc
.prev
.next
= hitDoc
.next
;
210 internal float score
;
212 internal Document doc
= null;
214 internal HitDoc next
; // in doubly-linked cache
215 internal HitDoc prev
; // in doubly-linked cache
217 internal HitDoc(float s
, int i
)