/*
 * 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.
 */
package org.apache.lucene.search;


import java.io.IOException;

import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.FilterNumericDocValues;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.index.SortedNumericDocValues;
import org.apache.lucene.util.NumericUtils;

Selects a value from the document's list to use as the representative value

This provides a NumericDocValues view over the SortedNumeric, for use with sorting, expressions, function queries, etc.

/** * Selects a value from the document's list to use as the representative value * <p> * This provides a NumericDocValues view over the SortedNumeric, for use with sorting, * expressions, function queries, etc. */
public class SortedNumericSelector {
Type of selection to perform.
/** * Type of selection to perform. */
public enum Type {
Selects the minimum value in the set
/** * Selects the minimum value in the set */
MIN,
Selects the maximum value in the set
/** * Selects the maximum value in the set */
MAX, // TODO: we could do MEDIAN in constant time (at most 2 lookups) }
Wraps a multi-valued SortedNumericDocValues as a single-valued view, using the specified selector and numericType.
/** * Wraps a multi-valued SortedNumericDocValues as a single-valued view, using the specified selector * and numericType. */
public static NumericDocValues wrap(SortedNumericDocValues sortedNumeric, Type selector, SortField.Type numericType) { if (numericType != SortField.Type.INT && numericType != SortField.Type.LONG && numericType != SortField.Type.FLOAT && numericType != SortField.Type.DOUBLE) { throw new IllegalArgumentException("numericType must be a numeric type"); } final NumericDocValues view; NumericDocValues singleton = DocValues.unwrapSingleton(sortedNumeric); if (singleton != null) { // it's actually single-valued in practice, but indexed as multi-valued, // so just sort on the underlying single-valued dv directly. // regardless of selector type, this optimization is safe! view = singleton; } else { switch(selector) { case MIN: view = new MinValue(sortedNumeric); break; case MAX: view = new MaxValue(sortedNumeric); break; default: throw new AssertionError(); } } // undo the numericutils sortability switch(numericType) { case FLOAT: return new FilterNumericDocValues(view) { @Override public long longValue() throws IOException { return NumericUtils.sortableFloatBits((int) in.longValue()); } }; case DOUBLE: return new FilterNumericDocValues(view) { @Override public long longValue() throws IOException { return NumericUtils.sortableDoubleBits(in.longValue()); } }; default: return view; } }
Wraps a SortedNumericDocValues and returns the first value (min)
/** Wraps a SortedNumericDocValues and returns the first value (min) */
static class MinValue extends NumericDocValues { final SortedNumericDocValues in; private long value; MinValue(SortedNumericDocValues in) { this.in = in; } @Override public int docID() { return in.docID(); } @Override public int nextDoc() throws IOException { int docID = in.nextDoc(); if (docID != NO_MORE_DOCS) { value = in.nextValue(); } return docID; } @Override public int advance(int target) throws IOException { int docID = in.advance(target); if (docID != NO_MORE_DOCS) { value = in.nextValue(); } return docID; } @Override public boolean advanceExact(int target) throws IOException { if (in.advanceExact(target)) { value = in.nextValue(); return true; } return false; } @Override public long cost() { return in.cost(); } @Override public long longValue() { return value; } }
Wraps a SortedNumericDocValues and returns the last value (max)
/** Wraps a SortedNumericDocValues and returns the last value (max) */
static class MaxValue extends NumericDocValues { final SortedNumericDocValues in; private long value; MaxValue(SortedNumericDocValues in) { this.in = in; } @Override public int docID() { return in.docID(); } private void setValue() throws IOException { int count = in.docValueCount(); for(int i=0;i<count;i++) { value = in.nextValue(); } } @Override public int nextDoc() throws IOException { int docID = in.nextDoc(); if (docID != NO_MORE_DOCS) { setValue(); } return docID; } @Override public int advance(int target) throws IOException { int docID = in.advance(target); if (docID != NO_MORE_DOCS) { setValue(); } return docID; } @Override public boolean advanceExact(int target) throws IOException { if (in.advanceExact(target)) { setValue(); return true; } return false; } @Override public long cost() { return in.cost(); } @Override public long longValue() { return value; } } }