@Override
    public void collect(int doc) throws IOException {
      ++totalHits;
      if (queueFull) {
        if ((reverseMul * comparator.compareBottom(doc)) <= 0) {
          // since docs are visited in doc Id order, if compare is 0, it means
          // this document is larger than anything else in the queue, and
          // therefore not competitive.
          return;
        }

        // This hit is competitive - replace bottom element in queue & adjustTop
        comparator.copy(bottom.slot, doc);
        updateBottom(doc);
        comparator.setBottom(bottom.slot);
      } else {
        // Startup transient: queue hasn't gathered numHits yet
        final int slot = totalHits - 1;
        // Copy hit into queue
        comparator.copy(slot, doc);
        add(slot, doc, Float.NaN);
        if (queueFull) {
          comparator.setBottom(bottom.slot);
        }
      }
    }
    public PagingFieldCollector(
        Sort sort,
        FieldValueHitQueue<Entry> queue,
        FieldDoc after,
        int numHits,
        boolean fillFields,
        boolean trackDocScores,
        boolean trackMaxScore) {
      super(queue, numHits, fillFields, trackDocScores || trackMaxScore || sort.needsScores());
      this.queue = queue;
      this.trackDocScores = trackDocScores;
      this.trackMaxScore = trackMaxScore;
      this.after = after;
      this.mayNeedScoresTwice = sort.needsScores() && (trackDocScores || trackMaxScore);

      // Must set maxScore to NEG_INF, or otherwise Math.max always returns NaN.
      maxScore = Float.NEGATIVE_INFINITY;

      FieldComparator<?>[] comparators = queue.comparators;
      // Tell all comparators their top value:
      for (int i = 0; i < comparators.length; i++) {
        @SuppressWarnings("unchecked")
        FieldComparator<Object> comparator = (FieldComparator<Object>) comparators[i];
        comparator.setTopValue(after.fields[i]);
      }
    }
Exemple #3
0
    // Returns true if first is < second
    @Override
    public boolean lessThan(ShardRef first, ShardRef second) {
      assert first != second;
      final FieldDoc firstFD = (FieldDoc) shardHits[first.shardIndex][first.hitIndex];
      final FieldDoc secondFD = (FieldDoc) shardHits[second.shardIndex][second.hitIndex];
      // System.out.println("  lessThan:\n     first=" + first + " doc=" + firstFD.doc + " score=" +
      // firstFD.score + "\n    second=" + second + " doc=" + secondFD.doc + " score=" +
      // secondFD.score);

      for (int compIDX = 0; compIDX < comparators.length; compIDX++) {
        final FieldComparator comp = comparators[compIDX];
        // System.out.println("    cmp idx=" + compIDX + " cmp1=" + firstFD.fields[compIDX] + "
        // cmp2=" + secondFD.fields[compIDX] + " reverse=" + reverseMul[compIDX]);

        final int cmp =
            reverseMul[compIDX]
                * comp.compareValues(firstFD.fields[compIDX], secondFD.fields[compIDX]);

        if (cmp != 0) {
          // System.out.println("    return " + (cmp < 0));
          return cmp < 0;
        }
      }

      // Tie break: earlier shard wins
      if (first.shardIndex < second.shardIndex) {
        // System.out.println("    return tb true");
        return true;
      } else if (first.shardIndex > second.shardIndex) {
        // System.out.println("    return tb false");
        return false;
      } else {
        // Tie break in same shard: resolve however the
        // shard had resolved it:
        // System.out.println("    return tb " + (first.hitIndex < second.hitIndex));
        assert first.hitIndex != second.hitIndex;
        return first.hitIndex < second.hitIndex;
      }
    }
  protected void doFieldSortValues(ResponseBuilder rb, SolrIndexSearcher searcher)
      throws IOException {
    SolrQueryRequest req = rb.req;
    SolrQueryResponse rsp = rb.rsp;

    // The query cache doesn't currently store sort field values, and SolrIndexSearcher doesn't
    // currently have an option to return sort field values.  Because of this, we
    // take the documents given and re-derive the sort values.
    boolean fsv = req.getParams().getBool(ResponseBuilder.FIELD_SORT_VALUES, false);
    if (fsv) {
      Sort sort = rb.getSortSpec().getSort();
      SortField[] sortFields =
          sort == null ? new SortField[] {SortField.FIELD_SCORE} : sort.getSort();
      NamedList sortVals = new NamedList(); // order is important for the sort fields
      Field field = new Field("dummy", "", Field.Store.YES, Field.Index.NO); // a dummy Field

      SolrIndexReader reader = searcher.getReader();
      SolrIndexReader[] readers = reader.getLeafReaders();
      SolrIndexReader subReader = reader;
      if (readers.length == 1) {
        // if there is a single segment, use that subReader and avoid looking up each time
        subReader = readers[0];
        readers = null;
      }
      int[] offsets = reader.getLeafOffsets();

      for (SortField sortField : sortFields) {
        int type = sortField.getType();
        if (type == SortField.SCORE || type == SortField.DOC) continue;

        FieldComparator comparator = null;
        FieldComparator comparators[] =
            (readers == null) ? null : new FieldComparator[readers.length];

        String fieldname = sortField.getField();
        FieldType ft = fieldname == null ? null : req.getSchema().getFieldTypeNoEx(fieldname);

        DocList docList = rb.getResults().docList;
        ArrayList<Object> vals = new ArrayList<Object>(docList.size());
        DocIterator it = rb.getResults().docList.iterator();

        int offset = 0;
        int idx = 0;

        while (it.hasNext()) {
          int doc = it.nextDoc();
          if (readers != null) {
            idx = SolrIndexReader.readerIndex(doc, offsets);
            subReader = readers[idx];
            offset = offsets[idx];
            comparator = comparators[idx];
          }

          if (comparator == null) {
            comparator = sortField.getComparator(1, 0);
            comparator = comparator.setNextReader(subReader, offset);
            if (comparators != null) comparators[idx] = comparator;
          }

          doc -= offset; // adjust for what segment this is in
          comparator.copy(0, doc);
          Object val = comparator.value(0);

          // Sortable float, double, int, long types all just use a string
          // comparator. For these, we need to put the type into a readable
          // format.  One reason for this is that XML can't represent all
          // string values (or even all unicode code points).
          // indexedToReadable() should be a no-op and should
          // thus be harmless anyway (for all current ways anyway)
          if (val instanceof String) {
            field.setValue((String) val);
            val = ft.toObject(field);
          }

          // Must do the same conversion when sorting by a
          // String field in Lucene, which returns the terms
          // data as BytesRef:
          if (val instanceof BytesRef) {
            field.setValue(((BytesRef) val).utf8ToString());
            val = ft.toObject(field);
          }

          vals.add(val);
        }

        sortVals.add(fieldname, vals);
      }

      rsp.add("sort_values", sortVals);
    }
  }
 @Override
 public void setScorer(Scorer scorer) throws IOException {
   comparator.setScorer(scorer);
 }
 @Override
 public void setNextReader(AtomicReaderContext context) throws IOException {
   this.docBase = context.docBase;
   queue.setComparator(0, comparator.setNextReader(context));
   comparator = queue.firstComparator;
 }
    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public void collect(int doc) throws IOException {
      totalHits++;

      // System.out.println("  collect doc=" + doc);

      // Check if this hit was already collected on a
      // previous page:
      boolean sameValues = true;
      for (int compIDX = 0; compIDX < comparators.length; compIDX++) {
        final FieldComparator comp = comparators[compIDX];

        final int cmp = reverseMul[compIDX] * comp.compareDocToValue(doc, after.fields[compIDX]);
        if (cmp < 0) {
          // Already collected on a previous page
          // System.out.println("    skip: before");
          return;
        } else if (cmp > 0) {
          // Not yet collected
          sameValues = false;
          // System.out.println("    keep: after");
          break;
        }
      }

      // Tie-break by docID:
      if (sameValues && doc <= afterDoc) {
        // Already collected on a previous page
        // System.out.println("    skip: tie-break");
        return;
      }

      collectedHits++;

      float score = Float.NaN;
      if (trackMaxScore) {
        score = scorer.score();
        if (score > maxScore) {
          maxScore = score;
        }
      }

      if (queueFull) {
        // Fastmatch: return if this hit is not competitive
        for (int i = 0; ; i++) {
          final int c = reverseMul[i] * comparators[i].compareBottom(doc);
          if (c < 0) {
            // Definitely not competitive.
            return;
          } else if (c > 0) {
            // Definitely competitive.
            break;
          } else if (i == comparators.length - 1) {
            // This is the equals case.
            if (doc + docBase > bottom.doc) {
              // Definitely not competitive
              return;
            }
            break;
          }
        }

        // This hit is competitive - replace bottom element in queue & adjustTop
        for (int i = 0; i < comparators.length; i++) {
          comparators[i].copy(bottom.slot, doc);
        }

        // Compute score only if it is competitive.
        if (trackDocScores && !trackMaxScore) {
          score = scorer.score();
        }
        updateBottom(doc, score);

        for (int i = 0; i < comparators.length; i++) {
          comparators[i].setBottom(bottom.slot);
        }
      } else {
        // Startup transient: queue hasn't gathered numHits yet
        final int slot = collectedHits - 1;
        // System.out.println("    slot=" + slot);
        // Copy hit into queue
        for (int i = 0; i < comparators.length; i++) {
          comparators[i].copy(slot, doc);
        }

        // Compute score only if it is competitive.
        if (trackDocScores && !trackMaxScore) {
          score = scorer.score();
        }
        bottom = pq.add(new Entry(slot, docBase + doc, score));
        queueFull = collectedHits == numHits;
        if (queueFull) {
          for (int i = 0; i < comparators.length; i++) {
            comparators[i].setBottom(bottom.slot);
          }
        }
      }
    }