QueryResponses.cs, DumpIndex.cs, IQueryResult.cs, QueryExecutor.cs, QueryResult.cs...
[beagle.git] / beagled / Lucene.Net / Search / Hits.cs
blob5824758811c619d1da4ff40e6d8041737648d6b8
1 /*
2 * Copyright 2004 The Apache Software Foundation
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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 System;
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)
41 weight = q.Weight(s);
42 searcher = s;
43 filter = f;
44 GetMoreDocs(50); // retrieve 100 initially
47 internal Hits(Searcher s, Query q, Filter f, Sort o)
49 weight = q.Weight(s);
50 searcher = s;
51 filter = f;
52 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.
58 /// </summary>
59 private void GetMoreDocs(int min)
61 if (hitDocs.Count > min)
63 min = hitDocs.Count;
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>
86 public int Length()
88 return length;
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.
94 /// </summary>
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)
104 // if cache is full
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
115 return hitDoc.doc;
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>
125 public int Id(int n)
127 return HitDoc(n).id;
130 /// <summary> Returns a {@link HitIterator} to navigate the Hits. Each item returned
131 /// from {@link Iterator#next()} is a {@link Hit}.
132 /// <p>
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.
136 /// </p>
137 /// </summary>
138 public System.Collections.IEnumerator Iterator()
140 return new HitIterator(this);
143 private HitDoc HitDoc(int n)
145 if (n >= length)
147 throw new System.IndexOutOfRangeException("Not a valid hit number: " + n);
150 if (n >= hitDocs.Count)
152 GetMoreDocs(n);
155 return (HitDoc) hitDocs[n];
158 private void AddToFront(HitDoc hitDoc)
160 // insert at front of cache
161 if (first == null)
163 last = hitDoc;
165 else
167 first.prev = hitDoc;
170 hitDoc.next = first;
171 first = hitDoc;
172 hitDoc.prev = null;
174 numDocs++;
177 private void Remove(HitDoc hitDoc)
179 // remove from cache
180 if (hitDoc.doc == null)
182 // it's not in the list
183 return ; // abort
186 if (hitDoc.next == null)
188 last = hitDoc.prev;
190 else
192 hitDoc.next.prev = hitDoc.prev;
195 if (hitDoc.prev == null)
197 first = hitDoc.next;
199 else
201 hitDoc.prev.next = hitDoc.next;
204 numDocs--;
208 sealed class HitDoc
210 internal float score;
211 internal int id;
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)
219 score = s;
220 id = i;