alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lucene example source code file (FieldValueHitQueue.java)

This example Lucene source code file (FieldValueHitQueue.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lucene tags/keywords

entry, entry, fieldcomparator, fieldcomparator, fieldvaluehitqueue, fieldvaluehitqueue, io, ioexception, multicomparatorsfieldvaluehitqueue, object, onecomparatorfieldvaluehitqueue, override, override, sortfield, string

The Lucene FieldValueHitQueue.java source code

package org.apache.lucene.search;

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;

import org.apache.lucene.util.PriorityQueue;

/**
 * Expert: A hit queue for sorting by hits by terms in more than one field.
 * Uses <code>FieldCache.DEFAULT for maintaining
 * internal term lookup tables.
 * 
 * @lucene.experimental
 * @since 2.9
 * @see Searcher#search(Query,Filter,int,Sort)
 * @see FieldCache
 */
public abstract class FieldValueHitQueue extends PriorityQueue<FieldValueHitQueue.Entry> {

  final static class Entry extends ScoreDoc {
    int slot;

    Entry(int slot, int doc, float score) {
      super(doc, score);
      this.slot = slot;
    }
    
    @Override
    public String toString() {
      return "slot:" + slot + " " + super.toString();
    }
  }

  /**
   * An implementation of {@link FieldValueHitQueue} which is optimized in case
   * there is just one comparator.
   */
  private static final class OneComparatorFieldValueHitQueue extends FieldValueHitQueue {

    private final FieldComparator comparator;
    private final int oneReverseMul;
    
    public OneComparatorFieldValueHitQueue(SortField[] fields, int size)
        throws IOException {
      super(fields);

      SortField field = fields[0];
      comparator = field.getComparator(size, 0);
      oneReverseMul = field.reverse ? -1 : 1;

      comparators[0] = comparator;
      reverseMul[0] = oneReverseMul;
      
      initialize(size);
    }

    /**
     * Returns whether <code>a is less relevant than b.
     * @param a ScoreDoc
     * @param b ScoreDoc
     * @return <code>true if document a should be sorted after document b.
     */
    @Override
    protected boolean lessThan(final Entry hitA, final Entry hitB) {

      assert hitA != hitB;
      assert hitA.slot != hitB.slot;

      final int c = oneReverseMul * comparator.compare(hitA.slot, hitB.slot);
      if (c != 0) {
        return c > 0;
      }

      // avoid random sort order that could lead to duplicates (bug #31241):
      return hitA.doc > hitB.doc;
    }

  }
  
  /**
   * An implementation of {@link FieldValueHitQueue} which is optimized in case
   * there is more than one comparator.
   */
  private static final class MultiComparatorsFieldValueHitQueue extends FieldValueHitQueue {

    public MultiComparatorsFieldValueHitQueue(SortField[] fields, int size)
        throws IOException {
      super(fields);

      int numComparators = comparators.length;
      for (int i = 0; i < numComparators; ++i) {
        SortField field = fields[i];

        reverseMul[i] = field.reverse ? -1 : 1;
        comparators[i] = field.getComparator(size, i);
      }

      initialize(size);
    }
  
    @Override
    protected boolean lessThan(final Entry hitA, final Entry hitB) {

      assert hitA != hitB;
      assert hitA.slot != hitB.slot;

      int numComparators = comparators.length;
      for (int i = 0; i < numComparators; ++i) {
        final int c = reverseMul[i] * comparators[i].compare(hitA.slot, hitB.slot);
        if (c != 0) {
          // Short circuit
          return c > 0;
        }
      }

      // avoid random sort order that could lead to duplicates (bug #31241):
      return hitA.doc > hitB.doc;
    }
    
  }
  
  // prevent instantiation and extension.
  private FieldValueHitQueue(SortField[] fields) {
    // When we get here, fields.length is guaranteed to be > 0, therefore no
    // need to check it again.
    
    // All these are required by this class's API - need to return arrays.
    // Therefore even in the case of a single comparator, create an array
    // anyway.
    this.fields = fields;
    int numComparators = fields.length;
    comparators = new FieldComparator[numComparators];
    reverseMul = new int[numComparators];
  }

  /**
   * Creates a hit queue sorted by the given list of fields.
   * 
   * <p>NOTE: The instances returned by this method
   * pre-allocate a full array of length <code>numHits.
   * 
   * @param fields
   *          SortField array we are sorting by in priority order (highest
   *          priority first); cannot be <code>null or empty
   * @param size
   *          The number of hits to retain. Must be greater than zero.
   * @throws IOException
   */
  public static FieldValueHitQueue create(SortField[] fields, int size) throws IOException {

    if (fields.length == 0) {
      throw new IllegalArgumentException("Sort must contain at least one field");
    }

    if (fields.length == 1) {
      return new OneComparatorFieldValueHitQueue(fields, size);
    } else {
      return new MultiComparatorsFieldValueHitQueue(fields, size);
    }
  }
  
  FieldComparator[] getComparators() { return comparators; }

  int[] getReverseMul() { return reverseMul; }

  /** Stores the sort criteria being used. */
  protected final SortField[] fields;
  protected final FieldComparator[] comparators;
  protected final int[] reverseMul;

  @Override
  protected abstract boolean lessThan (final Entry a, final Entry b);

  /**
   * Given a queue Entry, creates a corresponding FieldDoc
   * that contains the values used to sort the given document.
   * These values are not the raw values out of the index, but the internal
   * representation of them. This is so the given search hit can be collated by
   * a MultiSearcher with other search hits.
   * 
   * @param entry The Entry used to create a FieldDoc
   * @return The newly created FieldDoc
   * @see Searchable#search(Weight,Filter,int,Sort)
   */
  FieldDoc fillFields(final Entry entry) {
    final int n = comparators.length;
    final Object[] fields = new Object[n];
    for (int i = 0; i < n; ++i) {
      fields[i] = comparators[i].value(entry.slot);
    }
    //if (maxscore > 1.0f) doc.score /= maxscore;   // normalize scores
    return new FieldDoc(entry.doc, entry.score, fields);
  }

  /** Returns the SortFields being used by this hit queue. */
  SortField[] getFields() {
    return fields;
  }
}

Other Lucene examples (source code examples)

Here is a short list of links related to this Lucene FieldValueHitQueue.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.