Hits.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:5k
源码类别:

搜索引擎

开发平台:

C#

  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.
  15.  */
  16. using System;
  17. using Document = Lucene.Net.Documents.Document;
  18. namespace Lucene.Net.Search
  19. {
  20. /// <summary>A ranked list of documents, used to hold search results. </summary>
  21. public sealed class Hits
  22. {
  23. private Weight weight;
  24. private Searcher searcher;
  25. private Filter filter = null;
  26. private Sort sort = null;
  27. private int length; // the total number of hits
  28. private System.Collections.ArrayList hitDocs = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); // cache of hits retrieved
  29. private HitDoc first; // head of LRU cache
  30. private HitDoc last; // tail of LRU cache
  31. private int numDocs = 0; // number cached
  32. private int maxDocs = 200; // max to cache
  33. internal Hits(Searcher s, Query q, Filter f)
  34. {
  35. weight = q.Weight(s);
  36. searcher = s;
  37. filter = f;
  38. GetMoreDocs(50); // retrieve 100 initially
  39. }
  40. internal Hits(Searcher s, Query q, Filter f, Sort o)
  41. {
  42. weight = q.Weight(s);
  43. searcher = s;
  44. filter = f;
  45. sort = o;
  46. GetMoreDocs(50); // retrieve 100 initially
  47. }
  48. /// <summary> Tries to add new documents to hitDocs.
  49. /// Ensures that the hit numbered <code>min</code> has been retrieved.
  50. /// </summary>
  51. private void  GetMoreDocs(int min)
  52. {
  53. if (hitDocs.Count > min)
  54. {
  55. min = hitDocs.Count;
  56. }
  57. int n = min * 2; // double # retrieved
  58. TopDocs topDocs = (sort == null) ? searcher.Search(weight, filter, n) : searcher.Search(weight, filter, n, sort);
  59. length = topDocs.totalHits;
  60. ScoreDoc[] scoreDocs = topDocs.scoreDocs;
  61. float scoreNorm = 1.0f;
  62. if (length > 0 && topDocs.GetMaxScore() > 1.0f)
  63. {
  64. scoreNorm = 1.0f / topDocs.GetMaxScore();
  65. }
  66. int end = scoreDocs.Length < length?scoreDocs.Length:length;
  67. for (int i = hitDocs.Count; i < end; i++)
  68. {
  69. hitDocs.Add(new HitDoc(scoreDocs[i].score * scoreNorm, scoreDocs[i].doc));
  70. }
  71. }
  72. /// <summary>Returns the total number of hits available in this set. </summary>
  73. public int Length()
  74. {
  75. return length;
  76. }
  77. /// <summary>Returns the stored fields of the n<sup>th</sup> document in this set.
  78. /// <p>Documents are cached, so that repeated requests for the same element may
  79. /// return the same Document object. 
  80. /// </summary>
  81. public Document Doc(int n)
  82. {
  83. HitDoc hitDoc = HitDoc(n);
  84. // Update LRU cache of documents
  85. Remove(hitDoc); // remove from list, if there
  86. AddToFront(hitDoc); // add to front of list
  87. if (numDocs > maxDocs)
  88. {
  89. // if cache is full
  90. HitDoc oldLast = last;
  91. Remove(last); // flush last
  92. oldLast.doc = null; // let doc get gc'd
  93. }
  94. if (hitDoc.doc == null)
  95. {
  96. hitDoc.doc = searcher.Doc(hitDoc.id); // cache miss: read document
  97. }
  98. return hitDoc.doc;
  99. }
  100. /// <summary>Returns the score for the nth document in this set. </summary>
  101. public float Score(int n)
  102. {
  103. return HitDoc(n).score;
  104. }
  105. /// <summary>Returns the id for the nth document in this set. </summary>
  106. public int Id(int n)
  107. {
  108. return HitDoc(n).id;
  109. }
  110. /// <summary> Returns a {@link HitIterator} to navigate the Hits.  Each item returned
  111. /// from {@link Iterator#next()} is a {@link Hit}.
  112. /// <p>
  113. /// <b>Caution:</b> Iterate only over the hits needed.  Iterating over all
  114. /// hits is generally not desirable and may be the source of
  115. /// performance issues.
  116. /// </p>
  117. /// </summary>
  118. public System.Collections.IEnumerator Iterator()
  119. {
  120. return new HitIterator(this);
  121. }
  122. private HitDoc HitDoc(int n)
  123. {
  124. if (n >= length)
  125. {
  126. throw new System.IndexOutOfRangeException("Not a valid hit number: " + n);
  127. }
  128. if (n >= hitDocs.Count)
  129. {
  130. GetMoreDocs(n);
  131. }
  132. return (HitDoc) hitDocs[n];
  133. }
  134. private void  AddToFront(HitDoc hitDoc)
  135. {
  136. // insert at front of cache
  137. if (first == null)
  138. {
  139. last = hitDoc;
  140. }
  141. else
  142. {
  143. first.prev = hitDoc;
  144. }
  145. hitDoc.next = first;
  146. first = hitDoc;
  147. hitDoc.prev = null;
  148. numDocs++;
  149. }
  150. private void  Remove(HitDoc hitDoc)
  151. {
  152. // remove from cache
  153. if (hitDoc.doc == null)
  154. {
  155. // it's not in the list
  156. return ; // abort
  157. }
  158. if (hitDoc.next == null)
  159. {
  160. last = hitDoc.prev;
  161. }
  162. else
  163. {
  164. hitDoc.next.prev = hitDoc.prev;
  165. }
  166. if (hitDoc.prev == null)
  167. {
  168. first = hitDoc.next;
  169. }
  170. else
  171. {
  172. hitDoc.prev.next = hitDoc.next;
  173. }
  174. numDocs--;
  175. }
  176. }
  177. sealed class HitDoc
  178. {
  179. internal float score;
  180. internal int id;
  181. internal Document doc = null;
  182. internal HitDoc next; // in doubly-linked cache
  183. internal HitDoc prev; // in doubly-linked cache
  184. internal HitDoc(float s, int i)
  185. {
  186. score = s;
  187. id = i;
  188. }
  189. }
  190. }