diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 229773dec07..f583716a897 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -67,6 +67,8 @@ New Features modifying solr configuration files. (Erick Erickson) - SOLR-5539: Admin UI - Remove ability to create/modify files (steffkes) +* SOLR-6103: Added DateRangeField for indexing date ranges, especially + multi-valued ones. Based on LUCENE-5648. (David Smiley) Other Changes ---------------------- diff --git a/solr/core/src/java/org/apache/solr/schema/DateRangeField.java b/solr/core/src/java/org/apache/solr/schema/DateRangeField.java new file mode 100644 index 00000000000..74ff8f8b3d2 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/schema/DateRangeField.java @@ -0,0 +1,110 @@ +package org.apache.solr.schema; + +/* + * 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 com.spatial4j.core.shape.Shape; +import org.apache.lucene.index.StorableField; +import org.apache.lucene.search.Query; +import org.apache.lucene.spatial.NumberRangePrefixTreeStrategy; +import org.apache.lucene.spatial.prefix.tree.DateRangePrefixTree; +import org.apache.lucene.spatial.query.SpatialArgs; +import org.apache.lucene.spatial.query.SpatialOperation; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.search.QParser; + +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @see NumberRangePrefixTreeStrategy + * @see DateRangePrefixTree + */ +public class DateRangeField extends AbstractSpatialPrefixTreeFieldType { + + private static final String OP_PARAM = "op";//local-param to resolve SpatialOperation + + private final DateRangePrefixTree tree = DateRangePrefixTree.INSTANCE; + + @Override + protected void init(IndexSchema schema, Map args) { + super.init(schema, addDegrees(args)); + } + + private Map addDegrees(Map args) { + args.put("units", "degrees");//HACK! + return args; + } + + @Override + protected NumberRangePrefixTreeStrategy newPrefixTreeStrategy(String fieldName) { + return new NumberRangePrefixTreeStrategy(tree, fieldName); + } + + @Override + public List createFields(SchemaField field, Object val, float boost) { + if (val instanceof Date || val instanceof Calendar)//From URP + val = tree.toShape(val); + return super.createFields(field, val, boost); + } + + @Override + protected Shape parseShape(String str) { + try { + return tree.parseShape(str); + } catch (ParseException e) { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, + "Couldn't parse date because: "+ e.getMessage(), e); + } + } + + @Override + protected String shapeToString(Shape shape) { + return shape.toString();//generally round-trips for DateRangePrefixTree + } + + @Override + protected SpatialArgs parseSpatialArgs(QParser parser, String externalVal) { + //We avoid SpatialArgsParser entirely because it isn't very Solr-friendly + final Shape shape = parseShape(externalVal); + final SolrParams localParams = parser.getLocalParams(); + SpatialOperation op = SpatialOperation.Intersects; + if (localParams != null) { + String opStr = localParams.get(OP_PARAM); + if (opStr != null) + op = SpatialOperation.get(opStr); + } + return new SpatialArgs(op, shape); + } + + @Override + public Query getRangeQuery(QParser parser, SchemaField field, String part1, String part2, boolean minInclusive, boolean maxInclusive) { + if (!minInclusive || !maxInclusive) + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "exclusive range boundary not supported"); + if (part1 == null) + part1 = "*"; + if (part2 == null) + part2 = "*"; + Shape shape = tree.toRangeShape(parseShape(part1), parseShape(part2)); + SpatialArgs spatialArgs = new SpatialArgs(SpatialOperation.Intersects, shape); + return getQueryFromSpatialArgs(parser, field, spatialArgs); + } +} diff --git a/solr/core/src/test-files/solr/collection1/conf/schema.xml b/solr/core/src/test-files/solr/collection1/conf/schema.xml index 3ee60eb048c..40d43d59414 100644 --- a/solr/core/src/test-files/solr/collection1/conf/schema.xml +++ b/solr/core/src/test-files/solr/collection1/conf/schema.xml @@ -84,6 +84,7 @@ +