public static RangeEndpointCalculator<? extends Comparable<?>> create(RangeFacetRequest request) { final SchemaField sf = request.getField(); final FieldType ft = sf.getType(); final RangeEndpointCalculator<?> calc; if (ft instanceof TrieField) { final TrieField trie = (TrieField) ft; switch (trie.getType()) { case FLOAT: calc = new FloatRangeEndpointCalculator(request); break; case DOUBLE: calc = new DoubleRangeEndpointCalculator(request); break; case INTEGER: calc = new IntegerRangeEndpointCalculator(request); break; case LONG: calc = new LongRangeEndpointCalculator(request); break; default: throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on tried field of unexpected type:" + sf.getName()); } } else if (ft instanceof DateField) { calc = new DateRangeEndpointCalculator(request, null); } else { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on field:" + sf); } return calc; }
public void inform(IndexSchema schema) { FieldType doubleType = schema.getFieldTypeByName(doubleFieldName); if (doubleType == null) { throw new RuntimeException("Can not find double: " + doubleFieldName); } if (!(doubleType instanceof TrieDoubleField)) { throw new RuntimeException("double must be TrieDoubleField: " + doubleType); } // Just set these, delegate everything else to the field type int p = (INDEXED | TOKENIZED | OMIT_NORMS | OMIT_TF_POSITIONS); List<SchemaField> fields = new ArrayList<SchemaField>(schema.getFields().values()); for (SchemaField sf : fields) { if (sf.getType() == this) { String name = sf.getName(); schema .getFields() .put( name + TwoDoublesFieldInfo.SUFFIX_X, new SchemaField(name + TwoDoublesFieldInfo.SUFFIX_X, doubleType, p, null)); schema .getFields() .put( name + TwoDoublesFieldInfo.SUFFIX_Y, new SchemaField(name + TwoDoublesFieldInfo.SUFFIX_Y, doubleType, p, null)); } } TrieField df = (TrieField) doubleType; NumericFieldInfo info = new NumericFieldInfo(); info.setPrecisionStep(df.getPrecisionStep()); info.store = true; // TODO properties &... spatialStrategy = new TwoDoublesStrategy(ctx, info, FieldCache.NUMERIC_UTILS_DOUBLE_PARSER); spatialStrategy.setIgnoreIncompatibleGeometry(ignoreIncompatibleGeometry); }
/** * Term counts for use in field faceting that resepcts the specified mincount - if mincount is * null, the "zeros" param is consulted for the appropriate backcompat default * * @see FacetParams#FACET_ZEROS */ private NamedList<Integer> getTermCounts(String field, Integer mincount, ParsedParams parsed) throws IOException { final SolrParams params = parsed.params; final DocSet docs = parsed.docs; final int threads = parsed.threads; int offset = params.getFieldInt(field, FacetParams.FACET_OFFSET, 0); int limit = params.getFieldInt(field, FacetParams.FACET_LIMIT, 100); if (limit == 0) return new NamedList<>(); if (mincount == null) { Boolean zeros = params.getFieldBool(field, FacetParams.FACET_ZEROS); // mincount = (zeros!=null && zeros) ? 0 : 1; mincount = (zeros != null && !zeros) ? 1 : 0; // current default is to include zeros. } boolean missing = params.getFieldBool(field, FacetParams.FACET_MISSING, false); // default to sorting if there is a limit. String sort = params.getFieldParam( field, FacetParams.FACET_SORT, limit > 0 ? FacetParams.FACET_SORT_COUNT : FacetParams.FACET_SORT_INDEX); String prefix = params.getFieldParam(field, FacetParams.FACET_PREFIX); String contains = params.getFieldParam(field, FacetParams.FACET_CONTAINS); boolean ignoreCase = params.getFieldBool(field, FacetParams.FACET_CONTAINS_IGNORE_CASE, false); NamedList<Integer> counts; SchemaField sf = searcher.getSchema().getField(field); FieldType ft = sf.getType(); // determine what type of faceting method to use final String methodStr = params.getFieldParam(field, FacetParams.FACET_METHOD); FacetMethod method = null; if (FacetParams.FACET_METHOD_enum.equals(methodStr)) { method = FacetMethod.ENUM; } else if (FacetParams.FACET_METHOD_fcs.equals(methodStr)) { method = FacetMethod.FCS; } else if (FacetParams.FACET_METHOD_fc.equals(methodStr)) { method = FacetMethod.FC; } if (method == FacetMethod.ENUM && TrieField.getMainValuePrefix(ft) != null) { // enum can't deal with trie fields that index several terms per value method = sf.multiValued() ? FacetMethod.FC : FacetMethod.FCS; } if (method == null && ft instanceof BoolField) { // Always use filters for booleans... we know the number of values is very small. method = FacetMethod.ENUM; } final boolean multiToken = sf.multiValued() || ft.multiValuedFieldCache(); if (ft.getNumericType() != null && !sf.multiValued()) { // the per-segment approach is optimal for numeric field types since there // are no global ords to merge and no need to create an expensive // top-level reader method = FacetMethod.FCS; } if (method == null) { // TODO: default to per-segment or not? method = FacetMethod.FC; } if (method == FacetMethod.FCS && multiToken) { // only fc knows how to deal with multi-token fields method = FacetMethod.FC; } if (method == FacetMethod.ENUM && sf.hasDocValues()) { // only fc can handle docvalues types method = FacetMethod.FC; } if (params.getFieldBool(field, GroupParams.GROUP_FACET, false)) { counts = getGroupedCounts( searcher, docs, field, multiToken, offset, limit, mincount, missing, sort, prefix, contains, ignoreCase); } else { assert method != null; switch (method) { case ENUM: assert TrieField.getMainValuePrefix(ft) == null; counts = getFacetTermEnumCounts( searcher, docs, field, offset, limit, mincount, missing, sort, prefix, contains, ignoreCase, params); break; case FCS: assert !multiToken; if (ft.getNumericType() != null && !sf.multiValued()) { // force numeric faceting if (prefix != null && !prefix.isEmpty()) { throw new SolrException( ErrorCode.BAD_REQUEST, FacetParams.FACET_PREFIX + " is not supported on numeric types"); } if (contains != null && !contains.isEmpty()) { throw new SolrException( ErrorCode.BAD_REQUEST, FacetParams.FACET_CONTAINS + " is not supported on numeric types"); } counts = NumericFacets.getCounts( searcher, docs, field, offset, limit, mincount, missing, sort); } else { PerSegmentSingleValuedFaceting ps = new PerSegmentSingleValuedFaceting( searcher, docs, field, offset, limit, mincount, missing, sort, prefix, contains, ignoreCase); Executor executor = threads == 0 ? directExecutor : facetExecutor; ps.setNumThreads(threads); counts = ps.getFacetCounts(executor); } break; case FC: counts = DocValuesFacets.getCounts( searcher, docs, field, offset, limit, mincount, missing, sort, prefix, contains, ignoreCase); break; default: throw new AssertionError(); } } return counts; }