Package org.apache.lucene.facet.range

Source Code of org.apache.lucene.facet.range.RangeAccumulator$RangeSet

package org.apache.lucene.facet.range;

/*
* 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.search.FacetRequest;
import org.apache.lucene.facet.search.FacetResult;
import org.apache.lucene.facet.search.FacetResultNode;
import org.apache.lucene.facet.search.FacetsAccumulator;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.util.Bits;

/** Uses a {@link NumericDocValues} and accumulates
*  counts for provided ranges.  This is dynamic (does not
*  use the taxonomy index or anything from the index
*  except the NumericDocValuesField). */

public class RangeAccumulator extends FacetsAccumulator {

  static class RangeSet {
    final Range[] ranges;
    final String field;

    public RangeSet(Range[] ranges, String field) {
      this.ranges = ranges;
      this.field = field;
    }
  }

  final List<RangeSet> requests = new ArrayList<RangeSet>();

  public RangeAccumulator(FacetRequest... facetRequests) {
    this(Arrays.asList(facetRequests));
  }
 
  public RangeAccumulator(List<FacetRequest> facetRequests) {
    super(new FacetSearchParams(facetRequests));
    for (FacetRequest fr : facetRequests) {
      if (!(fr instanceof RangeFacetRequest)) {
        throw new IllegalArgumentException("this accumulator only supports RangeFacetRequest; got " + fr);
      }

      if (fr.categoryPath.length != 1) {
        throw new IllegalArgumentException("only flat (dimension only) CategoryPath is allowed");
      }
     
      RangeFacetRequest<?> rfr = (RangeFacetRequest<?>) fr;
      requests.add(new RangeSet(rfr.ranges, fr.categoryPath.components[0]));
    }
  }

  @Override
  public List<FacetResult> accumulate(List<MatchingDocs> matchingDocs) throws IOException {

    // TODO: test if this is faster (in the past it was
    // faster to do MachingDocs on the inside) ... see
    // patches on LUCENE-4965):
    List<FacetResult> results = new ArrayList<FacetResult>();
    for (int i = 0; i < requests.size(); i++) {
      RangeSet ranges = requests.get(i);

      int[] counts = new int[ranges.ranges.length];
      for (MatchingDocs hits : matchingDocs) {
        NumericDocValues ndv = hits.context.reader().getNumericDocValues(ranges.field);
        if (ndv == null) {
          continue; // no numeric values for this field in this reader
        }
        Bits docsWithField = hits.context.reader().getDocsWithField(ranges.field);

        final int length = hits.bits.length();
        int doc = 0;
        while (doc < length && (doc = hits.bits.nextSetBit(doc)) != -1) {
          long v = ndv.get(doc);

          // Skip missing docs:
          if (v == 0 && docsWithField.get(doc) == false) {
            doc++;
            continue;
          }

          // TODO: if all ranges are non-overlapping, we
          // should instead do a bin-search up front
          // (really, a specialized case of the interval
          // tree)
          // TODO: use interval tree instead of linear search:
          for (int j = 0; j < ranges.ranges.length; j++) {
            if (ranges.ranges[j].accept(v)) {
              counts[j]++;
            }
          }

          doc++;
        }
      }

      List<FacetResultNode> nodes = new ArrayList<FacetResultNode>(ranges.ranges.length);
      for(int j=0;j<ranges.ranges.length;j++) {
        nodes.add(new RangeFacetResultNode(ranges.field, ranges.ranges[j], counts[j]));
      }

      FacetResultNode rootNode = new FacetResultNode(-1, 0);
      rootNode.label = new CategoryPath(ranges.field);
      rootNode.subResults = nodes;

      results.add(new FacetResult(searchParams.facetRequests.get(i), rootNode, nodes.size()));
    }

    return results;
  }

  @Override
  public boolean requiresDocScores() {
    return false;
  }
}
TOP

Related Classes of org.apache.lucene.facet.range.RangeAccumulator$RangeSet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.