Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
FieldComparator.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using Lucene.Net.Support;
20 using IndexReader = Lucene.Net.Index.IndexReader;
21 using ByteParser = Lucene.Net.Search.ByteParser;
22 using DoubleParser = Lucene.Net.Search.DoubleParser;
23 using FloatParser = Lucene.Net.Search.FloatParser;
24 using IntParser = Lucene.Net.Search.IntParser;
25 using LongParser = Lucene.Net.Search.LongParser;
26 using ShortParser = Lucene.Net.Search.ShortParser;
27 using StringIndex = Lucene.Net.Search.StringIndex;
28 
29 namespace Lucene.Net.Search
30 {
31 
83  public abstract class FieldComparator
84  {
96  public abstract int Compare(int slot1, int slot2);
97 
106  public abstract void SetBottom(int slot);
107 
126  public abstract int CompareBottom(int doc);
127 
138  public abstract void Copy(int slot, int doc);
139 
149  public abstract void SetNextReader(IndexReader reader, int docBase);
150 
158  public virtual void SetScorer(Scorer scorer)
159  {
160  // Empty implementation since most comparators don't need the score. This
161  // can be overridden by those that need it.
162  }
163 
171  public abstract IComparable this[int slot] { get; }
172 
176  public sealed class ByteComparator:FieldComparator
177  {
178  private sbyte[] values;
179  private sbyte[] currentReaderValues;
180  private System.String field;
181  private ByteParser parser;
182  private sbyte bottom;
183 
184  internal ByteComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
185  {
186  values = new sbyte[numHits];
187  this.field = field;
188  this.parser = (ByteParser) parser;
189  }
190 
191  public override int Compare(int slot1, int slot2)
192  {
193  return values[slot1] - values[slot2];
194  }
195 
196  public override int CompareBottom(int doc)
197  {
198  return bottom - currentReaderValues[doc];
199  }
200 
201  public override void Copy(int slot, int doc)
202  {
203  values[slot] = currentReaderValues[doc];
204  }
205 
206  public override void SetNextReader(IndexReader reader, int docBase)
207  {
208  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetBytes(reader, field, parser);
209  }
210 
211  public override void SetBottom(int bottom)
212  {
213  this.bottom = values[bottom];
214  }
215 
216  public override IComparable this[int slot]
217  {
218  get { return (sbyte) values[slot]; }
219  }
220  }
221 
223  public sealed class DocComparator:FieldComparator
224  {
225  private int[] docIDs;
226  private int docBase;
227  private int bottom;
228 
229  internal DocComparator(int numHits)
230  {
231  docIDs = new int[numHits];
232  }
233 
234  public override int Compare(int slot1, int slot2)
235  {
236  // No overflow risk because docIDs are non-negative
237  return docIDs[slot1] - docIDs[slot2];
238  }
239 
240  public override int CompareBottom(int doc)
241  {
242  // No overflow risk because docIDs are non-negative
243  return bottom - (docBase + doc);
244  }
245 
246  public override void Copy(int slot, int doc)
247  {
248  docIDs[slot] = docBase + doc;
249  }
250 
251  public override void SetNextReader(IndexReader reader, int docBase)
252  {
253  // TODO: can we "map" our docIDs to the current
254  // reader? saves having to then subtract on every
255  // compare call
256  this.docBase = docBase;
257  }
258 
259  public override void SetBottom(int bottom)
260  {
261  this.bottom = docIDs[bottom];
262  }
263 
264  public override IComparable this[int slot]
265  {
266  get { return (System.Int32) docIDs[slot]; }
267  }
268  }
269 
273  public sealed class DoubleComparator:FieldComparator
274  {
275  private double[] values;
276  private double[] currentReaderValues;
277  private System.String field;
278  private DoubleParser parser;
279  private double bottom;
280 
281  internal DoubleComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
282  {
283  values = new double[numHits];
284  this.field = field;
285  this.parser = (DoubleParser) parser;
286  }
287 
288  public override int Compare(int slot1, int slot2)
289  {
290  double v1 = values[slot1];
291  double v2 = values[slot2];
292  if (v1 > v2)
293  {
294  return 1;
295  }
296  else if (v1 < v2)
297  {
298  return - 1;
299  }
300  else
301  {
302  return 0;
303  }
304  }
305 
306  public override int CompareBottom(int doc)
307  {
308  double v2 = currentReaderValues[doc];
309  if (bottom > v2)
310  {
311  return 1;
312  }
313  else if (bottom < v2)
314  {
315  return - 1;
316  }
317  else
318  {
319  return 0;
320  }
321  }
322 
323  public override void Copy(int slot, int doc)
324  {
325  values[slot] = currentReaderValues[doc];
326  }
327 
328  public override void SetNextReader(IndexReader reader, int docBase)
329  {
330  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetDoubles(reader, field, parser);
331  }
332 
333  public override void SetBottom(int bottom)
334  {
335  this.bottom = values[bottom];
336  }
337 
338  public override IComparable this[int slot]
339  {
340  get { return (double) values[slot]; }
341  }
342  }
343 
347  public sealed class FloatComparator:FieldComparator
348  {
349  private float[] values;
350  private float[] currentReaderValues;
351  private System.String field;
352  private FloatParser parser;
353  private float bottom;
354 
355  internal FloatComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
356  {
357  values = new float[numHits];
358  this.field = field;
359  this.parser = (FloatParser) parser;
360  }
361 
362  public override int Compare(int slot1, int slot2)
363  {
364  // TODO: are there sneaky non-branch ways to compute
365  // sign of float?
366  float v1 = values[slot1];
367  float v2 = values[slot2];
368  if (v1 > v2)
369  {
370  return 1;
371  }
372  else if (v1 < v2)
373  {
374  return - 1;
375  }
376  else
377  {
378  return 0;
379  }
380  }
381 
382  public override int CompareBottom(int doc)
383  {
384  // TODO: are there sneaky non-branch ways to compute
385  // sign of float?
386  float v2 = currentReaderValues[doc];
387  if (bottom > v2)
388  {
389  return 1;
390  }
391  else if (bottom < v2)
392  {
393  return - 1;
394  }
395  else
396  {
397  return 0;
398  }
399  }
400 
401  public override void Copy(int slot, int doc)
402  {
403  values[slot] = currentReaderValues[doc];
404  }
405 
406  public override void SetNextReader(IndexReader reader, int docBase)
407  {
408  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetFloats(reader, field, parser);
409  }
410 
411  public override void SetBottom(int bottom)
412  {
413  this.bottom = values[bottom];
414  }
415 
416  public override IComparable this[int slot]
417  {
418  get { return (float) values[slot]; }
419  }
420  }
421 
425  public sealed class IntComparator:FieldComparator
426  {
427  private int[] values;
428  private int[] currentReaderValues;
429  private System.String field;
430  private IntParser parser;
431  private int bottom; // Value of bottom of queue
432 
433  internal IntComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
434  {
435  values = new int[numHits];
436  this.field = field;
437  this.parser = (IntParser) parser;
438  }
439 
440  public override int Compare(int slot1, int slot2)
441  {
442  // TODO: there are sneaky non-branch ways to compute
443  // -1/+1/0 sign
444  // Cannot return values[slot1] - values[slot2] because that
445  // may overflow
446  int v1 = values[slot1];
447  int v2 = values[slot2];
448  if (v1 > v2)
449  {
450  return 1;
451  }
452  else if (v1 < v2)
453  {
454  return - 1;
455  }
456  else
457  {
458  return 0;
459  }
460  }
461 
462  public override int CompareBottom(int doc)
463  {
464  // TODO: there are sneaky non-branch ways to compute
465  // -1/+1/0 sign
466  // Cannot return bottom - values[slot2] because that
467  // may overflow
468  int v2 = currentReaderValues[doc];
469  if (bottom > v2)
470  {
471  return 1;
472  }
473  else if (bottom < v2)
474  {
475  return - 1;
476  }
477  else
478  {
479  return 0;
480  }
481  }
482 
483  public override void Copy(int slot, int doc)
484  {
485  values[slot] = currentReaderValues[doc];
486  }
487 
488  public override void SetNextReader(IndexReader reader, int docBase)
489  {
490  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetInts(reader, field, parser);
491  }
492 
493  public override void SetBottom(int bottom)
494  {
495  this.bottom = values[bottom];
496  }
497 
498  public override IComparable this[int slot]
499  {
500  get { return (System.Int32) values[slot]; }
501  }
502  }
503 
507  public sealed class LongComparator:FieldComparator
508  {
509  private long[] values;
510  private long[] currentReaderValues;
511  private System.String field;
512  private LongParser parser;
513  private long bottom;
514 
515  internal LongComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
516  {
517  values = new long[numHits];
518  this.field = field;
519  this.parser = (LongParser) parser;
520  }
521 
522  public override int Compare(int slot1, int slot2)
523  {
524  // TODO: there are sneaky non-branch ways to compute
525  // -1/+1/0 sign
526  long v1 = values[slot1];
527  long v2 = values[slot2];
528  if (v1 > v2)
529  {
530  return 1;
531  }
532  else if (v1 < v2)
533  {
534  return - 1;
535  }
536  else
537  {
538  return 0;
539  }
540  }
541 
542  public override int CompareBottom(int doc)
543  {
544  // TODO: there are sneaky non-branch ways to compute
545  // -1/+1/0 sign
546  long v2 = currentReaderValues[doc];
547  if (bottom > v2)
548  {
549  return 1;
550  }
551  else if (bottom < v2)
552  {
553  return - 1;
554  }
555  else
556  {
557  return 0;
558  }
559  }
560 
561  public override void Copy(int slot, int doc)
562  {
563  values[slot] = currentReaderValues[doc];
564  }
565 
566  public override void SetNextReader(IndexReader reader, int docBase)
567  {
568  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetLongs(reader, field, parser);
569  }
570 
571  public override void SetBottom(int bottom)
572  {
573  this.bottom = values[bottom];
574  }
575 
576  public override IComparable this[int slot]
577  {
578  get { return (long) values[slot]; }
579  }
580  }
581 
590  {
591  private float[] scores;
592  private float bottom;
593  private Scorer scorer;
594 
595  internal RelevanceComparator(int numHits)
596  {
597  scores = new float[numHits];
598  }
599 
600  public override int Compare(int slot1, int slot2)
601  {
602  float score1 = scores[slot1];
603  float score2 = scores[slot2];
604  return score1 > score2?- 1:(score1 < score2?1:0);
605  }
606 
607  public override int CompareBottom(int doc)
608  {
609  float score = scorer.Score();
610  return bottom > score?- 1:(bottom < score?1:0);
611  }
612 
613  public override void Copy(int slot, int doc)
614  {
615  scores[slot] = scorer.Score();
616  }
617 
618  public override void SetNextReader(IndexReader reader, int docBase)
619  {
620  }
621 
622  public override void SetBottom(int bottom)
623  {
624  this.bottom = scores[bottom];
625  }
626 
627  public override void SetScorer(Scorer scorer)
628  {
629  // wrap with a ScoreCachingWrappingScorer so that successive calls to
630  // score() will not incur score computation over and over again.
631  this.scorer = new ScoreCachingWrappingScorer(scorer);
632  }
633 
634  public override IComparable this[int slot]
635  {
636  get { return (float) scores[slot]; }
637  }
638  }
639 
643  public sealed class ShortComparator:FieldComparator
644  {
645  private short[] values;
646  private short[] currentReaderValues;
647  private System.String field;
648  private ShortParser parser;
649  private short bottom;
650 
651  internal ShortComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
652  {
653  values = new short[numHits];
654  this.field = field;
655  this.parser = (ShortParser) parser;
656  }
657 
658  public override int Compare(int slot1, int slot2)
659  {
660  return values[slot1] - values[slot2];
661  }
662 
663  public override int CompareBottom(int doc)
664  {
665  return bottom - currentReaderValues[doc];
666  }
667 
668  public override void Copy(int slot, int doc)
669  {
670  values[slot] = currentReaderValues[doc];
671  }
672 
673  public override void SetNextReader(IndexReader reader, int docBase)
674  {
675  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetShorts(reader, field, parser);
676  }
677 
678  public override void SetBottom(int bottom)
679  {
680  this.bottom = values[bottom];
681  }
682 
683  public override IComparable this[int slot]
684  {
685  get { return (short) values[slot]; }
686  }
687  }
688 
693  {
694 
695  private System.String[] values;
696  private System.String[] currentReaderValues;
697  private System.String field;
698  internal System.Globalization.CompareInfo collator;
699  private System.String bottom;
700 
701  internal StringComparatorLocale(int numHits, System.String field, System.Globalization.CultureInfo locale)
702  {
703  values = new System.String[numHits];
704  this.field = field;
705  collator = locale.CompareInfo;
706  }
707 
708  public override int Compare(int slot1, int slot2)
709  {
710  System.String val1 = values[slot1];
711  System.String val2 = values[slot2];
712  if (val1 == null)
713  {
714  if (val2 == null)
715  {
716  return 0;
717  }
718  return - 1;
719  }
720  else if (val2 == null)
721  {
722  return 1;
723  }
724  return collator.Compare(val1.ToString(), val2.ToString());
725  }
726 
727  public override int CompareBottom(int doc)
728  {
729  System.String val2 = currentReaderValues[doc];
730  if (bottom == null)
731  {
732  if (val2 == null)
733  {
734  return 0;
735  }
736  return - 1;
737  }
738  else if (val2 == null)
739  {
740  return 1;
741  }
742  return collator.Compare(bottom.ToString(), val2.ToString());
743  }
744 
745  public override void Copy(int slot, int doc)
746  {
747  values[slot] = currentReaderValues[doc];
748  }
749 
750  public override void SetNextReader(IndexReader reader, int docBase)
751  {
752  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStrings(reader, field);
753  }
754 
755  public override void SetBottom(int bottom)
756  {
757  this.bottom = values[bottom];
758  }
759 
760  public override IComparable this[int slot]
761  {
762  get { return values[slot]; }
763  }
764  }
765 
777  {
778 
779  private int[] ords;
780  private System.String[] values;
781  private int[] readerGen;
782 
783  private int currentReaderGen = - 1;
784  private System.String[] lookup;
785  private int[] order;
786  private System.String field;
787 
788  private int bottomSlot = - 1;
789  private int bottomOrd;
790  private System.String bottomValue;
791  private bool reversed;
792  private int sortPos;
793 
794  public StringOrdValComparator(int numHits, System.String field, int sortPos, bool reversed)
795  {
796  ords = new int[numHits];
797  values = new System.String[numHits];
798  readerGen = new int[numHits];
799  this.sortPos = sortPos;
800  this.reversed = reversed;
801  this.field = field;
802  }
803 
804  public override int Compare(int slot1, int slot2)
805  {
806  if (readerGen[slot1] == readerGen[slot2])
807  {
808  int cmp = ords[slot1] - ords[slot2];
809  if (cmp != 0)
810  {
811  return cmp;
812  }
813  }
814 
815  System.String val1 = values[slot1];
816  System.String val2 = values[slot2];
817  if (val1 == null)
818  {
819  if (val2 == null)
820  {
821  return 0;
822  }
823  return - 1;
824  }
825  else if (val2 == null)
826  {
827  return 1;
828  }
829  return String.CompareOrdinal(val1, val2);
830  }
831 
832  public override int CompareBottom(int doc)
833  {
834  System.Diagnostics.Debug.Assert(bottomSlot != - 1);
835  int order = this.order[doc];
836  int cmp = bottomOrd - order;
837  if (cmp != 0)
838  {
839  return cmp;
840  }
841 
842  System.String val2 = lookup[order];
843  if (bottomValue == null)
844  {
845  if (val2 == null)
846  {
847  return 0;
848  }
849  // bottom wins
850  return - 1;
851  }
852  else if (val2 == null)
853  {
854  // doc wins
855  return 1;
856  }
857  return String.CompareOrdinal(bottomValue, val2);
858  }
859 
860  private void Convert(int slot)
861  {
862  readerGen[slot] = currentReaderGen;
863  int index = 0;
864  System.String value_Renamed = values[slot];
865  if (value_Renamed == null)
866  {
867  ords[slot] = 0;
868  return ;
869  }
870 
871  if (sortPos == 0 && bottomSlot != - 1 && bottomSlot != slot)
872  {
873  // Since we are the primary sort, the entries in the
874  // queue are bounded by bottomOrd:
875  System.Diagnostics.Debug.Assert(bottomOrd < lookup.Length);
876  if (reversed)
877  {
878  index = BinarySearch(lookup, value_Renamed, bottomOrd, lookup.Length - 1);
879  }
880  else
881  {
882  index = BinarySearch(lookup, value_Renamed, 0, bottomOrd);
883  }
884  }
885  else
886  {
887  // Full binary search
888  index = BinarySearch(lookup, value_Renamed);
889  }
890 
891  if (index < 0)
892  {
893  index = - index - 2;
894  }
895  ords[slot] = index;
896  }
897 
898  public override void Copy(int slot, int doc)
899  {
900  int ord = order[doc];
901  ords[slot] = ord;
902  System.Diagnostics.Debug.Assert(ord >= 0);
903  values[slot] = lookup[ord];
904  readerGen[slot] = currentReaderGen;
905  }
906 
907  public override void SetNextReader(IndexReader reader, int docBase)
908  {
909  StringIndex currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStringIndex(reader, field);
910  currentReaderGen++;
911  order = currentReaderValues.order;
912  lookup = currentReaderValues.lookup;
913  System.Diagnostics.Debug.Assert(lookup.Length > 0);
914  if (bottomSlot != - 1)
915  {
916  Convert(bottomSlot);
917  bottomOrd = ords[bottomSlot];
918  }
919  }
920 
921  public override void SetBottom(int bottom)
922  {
923  bottomSlot = bottom;
924  if (readerGen[bottom] != currentReaderGen)
925  {
926  Convert(bottomSlot);
927  }
928  bottomOrd = ords[bottom];
929  System.Diagnostics.Debug.Assert(bottomOrd >= 0);
930  System.Diagnostics.Debug.Assert(bottomOrd < lookup.Length);
931  bottomValue = values[bottom];
932  }
933 
934  public override IComparable this[int slot]
935  {
936  get { return values[slot]; }
937  }
938 
939  public string[] GetValues()
940  {
941  return values;
942  }
943 
944  public int BottomSlot
945  {
946  get { return bottomSlot; }
947  }
948 
949  public string Field
950  {
951  get { return field; }
952  }
953  }
954 
961  {
962 
963  private System.String[] values;
964  private System.String[] currentReaderValues;
965  private System.String field;
966  private System.String bottom;
967 
968  internal StringValComparator(int numHits, System.String field)
969  {
970  values = new System.String[numHits];
971  this.field = field;
972  }
973 
974  public override int Compare(int slot1, int slot2)
975  {
976  System.String val1 = values[slot1];
977  System.String val2 = values[slot2];
978  if (val1 == null)
979  {
980  if (val2 == null)
981  {
982  return 0;
983  }
984  return - 1;
985  }
986  else if (val2 == null)
987  {
988  return 1;
989  }
990 
991  return String.CompareOrdinal(val1, val2);
992  }
993 
994  public override int CompareBottom(int doc)
995  {
996  System.String val2 = currentReaderValues[doc];
997  if (bottom == null)
998  {
999  if (val2 == null)
1000  {
1001  return 0;
1002  }
1003  return - 1;
1004  }
1005  else if (val2 == null)
1006  {
1007  return 1;
1008  }
1009  return String.CompareOrdinal(bottom, val2);
1010  }
1011 
1012  public override void Copy(int slot, int doc)
1013  {
1014  values[slot] = currentReaderValues[doc];
1015  }
1016 
1017  public override void SetNextReader(IndexReader reader, int docBase)
1018  {
1019  currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStrings(reader, field);
1020  }
1021 
1022  public override void SetBottom(int bottom)
1023  {
1024  this.bottom = values[bottom];
1025  }
1026 
1027  public override IComparable this[int slot]
1028  {
1029  get { return values[slot]; }
1030  }
1031  }
1032 
1033  protected internal static int BinarySearch(System.String[] a, System.String key)
1034  {
1035  return BinarySearch(a, key, 0, a.Length - 1);
1036  }
1037 
1038  protected internal static int BinarySearch(System.String[] a, System.String key, int low, int high)
1039  {
1040 
1041  while (low <= high)
1042  {
1043  int mid = Number.URShift((low + high), 1);
1044  System.String midVal = a[mid];
1045  int cmp;
1046  if (midVal != null)
1047  {
1048  cmp = String.CompareOrdinal(midVal, key);
1049  }
1050  else
1051  {
1052  cmp = - 1;
1053  }
1054 
1055  if (cmp < 0)
1056  low = mid + 1;
1057  else if (cmp > 0)
1058  high = mid - 1;
1059  else
1060  return mid;
1061  }
1062  return - (low + 1);
1063  }
1064  }
1065 }