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

搜索引擎

开发平台:

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 PriorityQueue = Lucene.Net.Util.PriorityQueue;
  18. namespace Lucene.Net.Search
  19. {
  20. /// <summary> Expert: Collects sorted results from Searchable's and collates them.
  21. /// The elements put into this queue must be of type FieldDoc.
  22. /// 
  23. /// <p>Created: Feb 11, 2004 2:04:21 PM
  24. /// 
  25. /// </summary>
  26. /// <author>   Tim Jones (Nacimiento Software)
  27. /// </author>
  28. /// <since>   lucene 1.4
  29. /// </since>
  30. /// <version>  $Id: FieldDocSortedHitQueue.java 332431 2005-11-11 03:13:10Z yonik $
  31. /// </version>
  32. class FieldDocSortedHitQueue : PriorityQueue
  33. {
  34. // this cannot contain AUTO fields - any AUTO fields should
  35. // have been resolved by the time this class is used.
  36. internal volatile SortField[] fields;
  37. // used in the case where the fields are sorted by locale
  38. // based strings
  39. internal volatile System.Globalization.CompareInfo[] collators;
  40. /// <summary> Creates a hit queue sorted by the given list of fields.</summary>
  41. /// <param name="fields">Field names, in priority order (highest priority first).
  42. /// </param>
  43. /// <param name="size"> The number of hits to retain.  Must be greater than zero.
  44. /// </param>
  45. internal FieldDocSortedHitQueue(SortField[] fields, int size)
  46. {
  47. this.fields = fields;
  48. this.collators = HasCollators(fields);
  49. Initialize(size);
  50. }
  51. /// <summary> Allows redefinition of sort fields if they are <code>null</code>.
  52. /// This is to handle the case using ParallelMultiSearcher where the
  53. /// original list contains AUTO and we don't know the actual sort
  54. /// type until the values come back.  The fields can only be set once.
  55. /// This method is thread safe.
  56. /// </summary>
  57. /// <param name="fields">
  58. /// </param>
  59. internal virtual void  SetFields(SortField[] fields)
  60. {
  61. lock (this)
  62. {
  63. if (this.fields == null)
  64. {
  65. this.fields = fields;
  66. this.collators = HasCollators(fields);
  67. }
  68. }
  69. }
  70. /// <summary>Returns the fields being used to sort. </summary>
  71. internal virtual SortField[] GetFields()
  72. {
  73. return fields;
  74. }
  75. /// <summary>Returns an array of collators, possibly <code>null</code>.  The collators
  76. /// correspond to any SortFields which were given a specific locale.
  77. /// </summary>
  78. /// <param name="fields">Array of sort fields.
  79. /// </param>
  80. /// <returns> Array, possibly <code>null</code>.
  81. /// </returns>
  82. private System.Globalization.CompareInfo[] HasCollators(SortField[] fields)
  83. {
  84. if (fields == null)
  85. return null;
  86. System.Globalization.CompareInfo[] ret = new System.Globalization.CompareInfo[fields.Length];
  87. for (int i = 0; i < fields.Length; ++i)
  88. {
  89. System.Globalization.CultureInfo locale = fields[i].GetLocale();
  90. if (locale != null)
  91. ret[i] = locale.CompareInfo;
  92. }
  93. return ret;
  94. }
  95. /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
  96. /// <param name="a">ScoreDoc
  97. /// </param>
  98. /// <param name="b">ScoreDoc
  99. /// </param>
  100. /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
  101. /// </returns>
  102. public override bool LessThan(System.Object a, System.Object b)
  103. {
  104. FieldDoc docA = (FieldDoc) a;
  105. FieldDoc docB = (FieldDoc) b;
  106. int n = fields.Length;
  107. int c = 0;
  108. for (int i = 0; i < n && c == 0; ++i)
  109. {
  110. int type = fields[i].GetType();
  111. switch (type)
  112. {
  113. case SortField.SCORE: 
  114. float r1 = (float) ((System.Single) docA.fields[i]);
  115. float r2 = (float) ((System.Single) docB.fields[i]);
  116. if (r1 > r2)
  117. c = - 1;
  118. if (r1 < r2)
  119. c = 1;
  120. break;
  121. case SortField.DOC: 
  122. case SortField.INT: 
  123. int i1 = ((System.Int32) docA.fields[i]);
  124. int i2 = ((System.Int32) docB.fields[i]);
  125. if (i1 < i2)
  126. c = - 1;
  127. if (i1 > i2)
  128. c = 1;
  129. break;
  130. case SortField.STRING: 
  131. System.String s1 = (System.String) docA.fields[i];
  132. System.String s2 = (System.String) docB.fields[i];
  133. // null values need to be sorted first, because of how FieldCache.getStringIndex()
  134. // works - in that routine, any documents without a value in the given field are
  135. // put first.  If both are null, the next SortField is used
  136. if (s1 == null)
  137. c = (s2 == null)?0:- 1;
  138. else if (s2 == null)
  139. c = 1;
  140. // 
  141. else if (fields[i].GetLocale() == null)
  142. {
  143. c = String.CompareOrdinal(s1, s2);
  144. }
  145. else
  146. {
  147. //UPGRADE_TODO: The equivalent in .NET for method 'java.text.Collator.compare' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
  148. c = collators[i].Compare(s1.ToString(), s2.ToString());
  149. }
  150. break;
  151. case SortField.FLOAT: 
  152. //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
  153. float f1 = (float) ((System.Single) docA.fields[i]);
  154. //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
  155. float f2 = (float) ((System.Single) docB.fields[i]);
  156. if (f1 < f2)
  157. c = - 1;
  158. if (f1 > f2)
  159. c = 1;
  160. break;
  161. case SortField.CUSTOM: 
  162. c = docA.fields[i].CompareTo(docB.fields[i]);
  163. break;
  164. case SortField.AUTO: 
  165. // we cannot handle this - even if we determine the type of object (Float or
  166. // Integer), we don't necessarily know how to compare them (both SCORE and
  167. // FLOAT contain floats, but are sorted opposite of each other). Before
  168. // we get here, each AUTO should have been replaced with its actual value.
  169. throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
  170. default: 
  171. throw new System.SystemException("invalid SortField type: " + type);
  172. }
  173. if (fields[i].GetReverse())
  174. {
  175. c = - c;
  176. }
  177. }
  178. // avoid random sort order that could lead to duplicates (bug #31241):
  179. if (c == 0)
  180. return docA.doc > docB.doc;
  181. return c > 0;
  182. }
  183. }
  184. }