mirror of https://github.com/apache/lucene.git
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/lucene-solr
This commit is contained in:
commit
b125107b7c
|
@ -129,6 +129,8 @@ Bug Fixes
|
|||
|
||||
* SOLR-10101: TestLazyCores hangs (Erick Erickson)
|
||||
|
||||
* SOLR-11332: Fix sorting on 'enum' fieldTypes that use sortMissingFirst or sortMissingLast (hossman)
|
||||
|
||||
Optimizations
|
||||
----------------------
|
||||
|
||||
|
@ -199,6 +201,10 @@ Other Changes
|
|||
|
||||
* SOLR-10990: Breakup QueryComponent.process method for readability. (Christine Poerschke)
|
||||
|
||||
* SOLR-11132: Refactor common getSortField logic in various FieldTypes (Jason Gerlowski, hossman)
|
||||
|
||||
* SOLR-11351: Make LTRScoringModel model more extensible. (Christine Poerschke)
|
||||
|
||||
================== 7.0.0 ==================
|
||||
|
||||
Versions of Major Components
|
||||
|
|
|
@ -80,7 +80,7 @@ public abstract class LTRScoringModel {
|
|||
protected final List<Feature> features;
|
||||
private final List<Feature> allFeatures;
|
||||
private final Map<String,Object> params;
|
||||
private final List<Normalizer> norms;
|
||||
protected final List<Normalizer> norms;
|
||||
|
||||
public static LTRScoringModel getInstance(SolrResourceLoader solrResourceLoader,
|
||||
String className, String name, List<Feature> features,
|
||||
|
@ -123,6 +123,8 @@ public abstract class LTRScoringModel {
|
|||
* {@link ModelException} if they do not make sense.
|
||||
*/
|
||||
protected void validate() throws ModelException {
|
||||
final List<Feature> features = getFeatures();
|
||||
final List<Normalizer> norms = getNorms();
|
||||
if (features.isEmpty()) {
|
||||
throw new ModelException("no features declared for model "+name);
|
||||
}
|
||||
|
|
|
@ -239,12 +239,14 @@ public class TestRerankBase extends RestTestBase {
|
|||
.append(",\n");
|
||||
sb.append("\"class\":").append('"').append(type).append('"').append(",\n");
|
||||
sb.append("\"features\":").append('[');
|
||||
for (final String feature : features) {
|
||||
sb.append("\n\t{ ");
|
||||
sb.append("\"name\":").append('"').append(feature).append('"')
|
||||
.append("},");
|
||||
if (features.length > 0) {
|
||||
for (final String feature : features) {
|
||||
sb.append("\n\t{ ");
|
||||
sb.append("\"name\":").append('"').append(feature).append('"')
|
||||
.append("},");
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
sb.append("\n]\n");
|
||||
if (params != null) {
|
||||
sb.append(",\n");
|
||||
|
|
|
@ -296,6 +296,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
|
|||
.withFunctionName("probability", ProbabilityEvaluator.class)
|
||||
.withFunctionName("sumDifference", SumDifferenceEvaluator.class)
|
||||
.withFunctionName("meanDifference", MeanDifferenceEvaluator.class)
|
||||
.withFunctionName("primes", PrimesEvaluator.class)
|
||||
|
||||
// Boolean Stream Evaluators
|
||||
|
||||
|
|
|
@ -357,14 +357,14 @@ public class QueryComponent extends SearchComponent
|
|||
cmd.setSegmentTerminateEarly(false); // not supported, silently ignore any segmentTerminateEarly flag
|
||||
try {
|
||||
if (params.getBool(GroupParams.GROUP_DISTRIBUTED_FIRST, false)) {
|
||||
doProcessGroupedDistributedSearchFirstPhase(rb, result);
|
||||
doProcessGroupedDistributedSearchFirstPhase(rb, cmd, result);
|
||||
return;
|
||||
} else if (params.getBool(GroupParams.GROUP_DISTRIBUTED_SECOND, false)) {
|
||||
doProcessGroupedDistributedSearchSecondPhase(rb, result);
|
||||
doProcessGroupedDistributedSearchSecondPhase(rb, cmd, result);
|
||||
return;
|
||||
}
|
||||
|
||||
doProcessGroupedSearch(rb, result);
|
||||
doProcessGroupedSearch(rb, cmd, result);
|
||||
return;
|
||||
} catch (SyntaxError e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
|
||||
|
@ -372,7 +372,7 @@ public class QueryComponent extends SearchComponent
|
|||
}
|
||||
|
||||
// normal search result
|
||||
doProcessUngroupedSearch(rb, result);
|
||||
doProcessUngroupedSearch(rb, cmd, result);
|
||||
}
|
||||
|
||||
protected void doFieldSortValues(ResponseBuilder rb, SolrIndexSearcher searcher) throws IOException
|
||||
|
@ -1248,7 +1248,7 @@ public class QueryComponent extends SearchComponent
|
|||
return true;
|
||||
}
|
||||
|
||||
private void doProcessGroupedDistributedSearchFirstPhase(ResponseBuilder rb, QueryResult result) throws IOException {
|
||||
private void doProcessGroupedDistributedSearchFirstPhase(ResponseBuilder rb, QueryCommand cmd, QueryResult result) throws IOException {
|
||||
|
||||
GroupingSpecification groupingSpec = rb.getGroupingSpec();
|
||||
assert null != groupingSpec : "GroupingSpecification is null";
|
||||
|
@ -1259,8 +1259,6 @@ public class QueryComponent extends SearchComponent
|
|||
SolrIndexSearcher searcher = req.getSearcher();
|
||||
IndexSchema schema = searcher.getSchema();
|
||||
|
||||
QueryCommand cmd = rb.getQueryCommand();
|
||||
|
||||
CommandHandler.Builder topsGroupsActionBuilder = new CommandHandler.Builder()
|
||||
.setQueryCommand(cmd)
|
||||
.setNeedDocSet(false) // Order matters here
|
||||
|
@ -1286,7 +1284,7 @@ public class QueryComponent extends SearchComponent
|
|||
rb.setResult(result);
|
||||
}
|
||||
|
||||
private void doProcessGroupedDistributedSearchSecondPhase(ResponseBuilder rb, QueryResult result) throws IOException, SyntaxError {
|
||||
private void doProcessGroupedDistributedSearchSecondPhase(ResponseBuilder rb, QueryCommand cmd, QueryResult result) throws IOException, SyntaxError {
|
||||
|
||||
GroupingSpecification groupingSpec = rb.getGroupingSpec();
|
||||
assert null != groupingSpec : "GroupingSpecification is null";
|
||||
|
@ -1299,7 +1297,6 @@ public class QueryComponent extends SearchComponent
|
|||
SolrIndexSearcher searcher = req.getSearcher();
|
||||
IndexSchema schema = searcher.getSchema();
|
||||
|
||||
QueryCommand cmd = rb.getQueryCommand();
|
||||
boolean needScores = (cmd.getFlags() & SolrIndexSearcher.GET_SCORES) != 0;
|
||||
|
||||
CommandHandler.Builder secondPhaseBuilder = new CommandHandler.Builder()
|
||||
|
@ -1358,7 +1355,7 @@ public class QueryComponent extends SearchComponent
|
|||
rb.setResult(result);
|
||||
}
|
||||
|
||||
private void doProcessGroupedSearch(ResponseBuilder rb, QueryResult result) throws IOException, SyntaxError {
|
||||
private void doProcessGroupedSearch(ResponseBuilder rb, QueryCommand cmd, QueryResult result) throws IOException, SyntaxError {
|
||||
|
||||
GroupingSpecification groupingSpec = rb.getGroupingSpec();
|
||||
assert null != groupingSpec : "GroupingSpecification is null";
|
||||
|
@ -1370,8 +1367,6 @@ public class QueryComponent extends SearchComponent
|
|||
|
||||
SolrIndexSearcher searcher = req.getSearcher();
|
||||
|
||||
QueryCommand cmd = rb.getQueryCommand();
|
||||
|
||||
int maxDocsPercentageToCache = params.getInt(GroupParams.GROUP_CACHE_PERCENTAGE, 0);
|
||||
boolean cacheSecondPassSearch = maxDocsPercentageToCache >= 1 && maxDocsPercentageToCache <= 100;
|
||||
Grouping.TotalCount defaultTotalCount = groupingSpec.isIncludeGroupCount() ?
|
||||
|
@ -1430,15 +1425,13 @@ public class QueryComponent extends SearchComponent
|
|||
}
|
||||
}
|
||||
|
||||
private void doProcessUngroupedSearch(ResponseBuilder rb, QueryResult result) throws IOException {
|
||||
private void doProcessUngroupedSearch(ResponseBuilder rb, QueryCommand cmd, QueryResult result) throws IOException {
|
||||
|
||||
SolrQueryRequest req = rb.req;
|
||||
SolrQueryResponse rsp = rb.rsp;
|
||||
|
||||
SolrIndexSearcher searcher = req.getSearcher();
|
||||
|
||||
QueryCommand cmd = rb.getQueryCommand();
|
||||
|
||||
searcher.search(result, cmd);
|
||||
rb.setResult(result);
|
||||
|
||||
|
|
|
@ -250,11 +250,12 @@ public abstract class AbstractEnumField extends PrimitiveFieldType {
|
|||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean top) {
|
||||
field.checkSortability();
|
||||
final Object missingValue = Integer.MIN_VALUE;
|
||||
SortField sf = new SortField(field.getName(), SortField.Type.INT, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
SortField result = getSortField(field, SortField.Type.INT, top, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||
if (null == result.getMissingValue()) {
|
||||
// special case default behavior: assume missing values are "below" all enum values
|
||||
result.setMissingValue(Integer.MIN_VALUE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -190,20 +190,7 @@ public class DatePointField extends PointField implements DateValueFieldType {
|
|||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean top) {
|
||||
field.checkSortability();
|
||||
|
||||
Object missingValue = null;
|
||||
boolean sortMissingLast = field.sortMissingLast();
|
||||
boolean sortMissingFirst = field.sortMissingFirst();
|
||||
|
||||
if (sortMissingLast) {
|
||||
missingValue = top ? Long.MIN_VALUE : Long.MAX_VALUE;
|
||||
} else if (sortMissingFirst) {
|
||||
missingValue = top ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
SortField sf = new SortField(field.getName(), SortField.Type.LONG, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
return getSortField(field, SortField.Type.LONG, top, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -134,20 +134,7 @@ public class DoublePointField extends PointField implements DoubleValueFieldType
|
|||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean top) {
|
||||
field.checkSortability();
|
||||
|
||||
Object missingValue = null;
|
||||
boolean sortMissingLast = field.sortMissingLast();
|
||||
boolean sortMissingFirst = field.sortMissingFirst();
|
||||
|
||||
if (sortMissingLast) {
|
||||
missingValue = top ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
|
||||
} else if (sortMissingFirst) {
|
||||
missingValue = top ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
SortField sf = new SortField(field.getName(), SortField.Type.DOUBLE, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
return getSortField(field, SortField.Type.DOUBLE, top, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.apache.lucene.search.MultiTermQuery;
|
|||
import org.apache.lucene.search.PrefixQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.lucene.search.SortedSetSortField;
|
||||
import org.apache.lucene.search.SortedNumericSelector;
|
||||
import org.apache.lucene.search.SortedSetSelector;
|
||||
import org.apache.lucene.search.TermInSetQuery;
|
||||
|
@ -69,7 +70,6 @@ import org.apache.solr.query.SolrRangeQuery;
|
|||
import org.apache.solr.response.TextResponseWriter;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.QueryUtils;
|
||||
import org.apache.solr.search.Sorting;
|
||||
import org.apache.solr.uninverting.UninvertingReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -662,17 +662,76 @@ public abstract class FieldType extends FieldProperties {
|
|||
* Returns the SortField instance that should be used to sort fields
|
||||
* of this type.
|
||||
* @see SchemaField#checkSortability
|
||||
* @see #getSortField(SchemaField,SortField.Type,boolean,Object,Object)
|
||||
*/
|
||||
public abstract SortField getSortField(SchemaField field, boolean top);
|
||||
|
||||
/**
|
||||
* <p>A Helper utility method for use by subclasses.</p>
|
||||
* <p>This method deals with:</p>
|
||||
* <ul>
|
||||
* <li>{@link SchemaField#checkSortability}</li>
|
||||
* <li>Creating a {@link SortField} on <code>field</code> with the specified
|
||||
* <code>reverse</code> & <code>sortType</code></li>
|
||||
* <li>Setting the {@link SortField#setMissingValue} to <code>missingLow</code> or <code>missingHigh</code>
|
||||
* as appropriate based on the value of <code>reverse</code> and the
|
||||
* <code>sortMissingFirst</code> & <code>sortMissingLast</code> properties of the
|
||||
* <code>field</code></li>
|
||||
* </ul>
|
||||
*
|
||||
* @param field The SchemaField to sort on. May use <code>sortMissingFirst</code> or <code>sortMissingLast</code> or neither.
|
||||
* @param sortType The sort Type of the underlying values in the <code>field</code>
|
||||
* @param reverse True if natural order of the <code>sortType</code> should be reversed
|
||||
* @param missingLow The <code>missingValue</code> to be used if the other params indicate that docs w/o values should sort as "low" as possible.
|
||||
* @param missingHigh The <code>missingValue</code> to be used if the other params indicate that docs w/o values should sort as "high" as possible.
|
||||
* @see #getSortedSetSortField
|
||||
*/
|
||||
protected static SortField getSortField(SchemaField field, SortField.Type sortType, boolean reverse,
|
||||
Object missingLow, Object missingHigh) {
|
||||
field.checkSortability();
|
||||
|
||||
SortField sf = new SortField(field.getName(), sortType, reverse);
|
||||
applySetMissingValue(field, sf, missingLow, missingHigh);
|
||||
|
||||
return sf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #getSortField} but using {@link SortedSetSortField}
|
||||
*/
|
||||
protected static SortField getSortedSetSortField(SchemaField field, SortedSetSelector.Type selector,
|
||||
boolean reverse, Object missingLow, Object missingHigh) {
|
||||
|
||||
field.checkSortability();
|
||||
|
||||
SortField sf = new SortedSetSortField(field.getName(), reverse, selector);
|
||||
applySetMissingValue(field, sf, missingLow, missingHigh);
|
||||
|
||||
return sf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getSortField
|
||||
* @see #getSortedSetSortField
|
||||
*/
|
||||
private static void applySetMissingValue(SchemaField field, SortField sortField,
|
||||
Object missingLow, Object missingHigh) {
|
||||
final boolean reverse = sortField.getReverse();
|
||||
|
||||
if (field.sortMissingLast()) {
|
||||
sortField.setMissingValue(reverse ? missingLow : missingHigh);
|
||||
} else if (field.sortMissingFirst()) {
|
||||
sortField.setMissingValue(reverse ? missingHigh : missingLow);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility usable by subclasses when they want to get basic String sorting
|
||||
* using common checks.
|
||||
* @see SchemaField#checkSortability
|
||||
*/
|
||||
protected SortField getStringSort(SchemaField field, boolean reverse) {
|
||||
field.checkSortability();
|
||||
return Sorting.getStringSortField(field.name, reverse, field.sortMissingLast(),field.sortMissingFirst());
|
||||
return getSortField(field, SortField.Type.STRING, reverse, SortField.STRING_FIRST, SortField.STRING_LAST);
|
||||
}
|
||||
|
||||
/** called to get the default value source (normally, from the
|
||||
|
|
|
@ -134,20 +134,7 @@ public class FloatPointField extends PointField implements FloatValueFieldType {
|
|||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean top) {
|
||||
field.checkSortability();
|
||||
|
||||
Object missingValue = null;
|
||||
boolean sortMissingLast = field.sortMissingLast();
|
||||
boolean sortMissingFirst = field.sortMissingFirst();
|
||||
|
||||
if (sortMissingLast) {
|
||||
missingValue = top ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
|
||||
} else if (sortMissingFirst) {
|
||||
missingValue = top ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
|
||||
}
|
||||
SortField sf = new SortField(field.getName(), SortField.Type.FLOAT, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
return getSortField(field, SortField.Type.FLOAT, top, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -132,20 +132,7 @@ public class IntPointField extends PointField implements IntValueFieldType {
|
|||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean top) {
|
||||
field.checkSortability();
|
||||
|
||||
Object missingValue = null;
|
||||
boolean sortMissingLast = field.sortMissingLast();
|
||||
boolean sortMissingFirst = field.sortMissingFirst();
|
||||
|
||||
if (sortMissingLast) {
|
||||
missingValue = top ? Integer.MIN_VALUE : Integer.MAX_VALUE;
|
||||
} else if (sortMissingFirst) {
|
||||
missingValue = top ? Integer.MAX_VALUE : Integer.MIN_VALUE;
|
||||
}
|
||||
SortField sf = new SortField(field.getName(), SortField.Type.INT, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
return getSortField(field, SortField.Type.INT, top, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -131,20 +131,7 @@ public class LongPointField extends PointField implements LongValueFieldType {
|
|||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean top) {
|
||||
field.checkSortability();
|
||||
|
||||
Object missingValue = null;
|
||||
boolean sortMissingLast = field.sortMissingLast();
|
||||
boolean sortMissingFirst = field.sortMissingFirst();
|
||||
|
||||
if (sortMissingLast) {
|
||||
missingValue = top ? Long.MIN_VALUE : Long.MAX_VALUE;
|
||||
} else if (sortMissingFirst) {
|
||||
missingValue = top ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
SortField sf = new SortField(field.getName(), SortField.Type.LONG, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
return getSortField(field, SortField.Type.LONG, top, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,13 +34,13 @@ import org.apache.lucene.index.IndexableField;
|
|||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.valuesource.SortedSetFieldSource;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.lucene.search.SortedSetSelector;
|
||||
import org.apache.lucene.util.AttributeFactory;
|
||||
import org.apache.lucene.util.AttributeSource.State;
|
||||
import org.apache.lucene.util.AttributeSource;
|
||||
import org.apache.solr.analysis.SolrAnalyzer;
|
||||
import org.apache.solr.response.TextResponseWriter;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.Sorting;
|
||||
import org.apache.solr.uninverting.UninvertingReader.Type;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -132,8 +132,8 @@ public class PreAnalyzedField extends TextField implements HasImplicitIndexAnaly
|
|||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean top) {
|
||||
field.checkSortability();
|
||||
return Sorting.getTextSortField(field.getName(), top, field.sortMissingLast(), field.sortMissingFirst());
|
||||
return getSortedSetSortField(field, SortedSetSelector.Type.MIN, top,
|
||||
SortField.STRING_FIRST, SortField.STRING_LAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.apache.solr.common.SolrException;
|
|||
import org.apache.solr.query.SolrRangeQuery;
|
||||
import org.apache.solr.response.TextResponseWriter;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.Sorting;
|
||||
import org.apache.solr.uninverting.UninvertingReader.Type;
|
||||
|
||||
/** <code>TextField</code> is the basic type for configurable text analysis.
|
||||
|
@ -108,8 +107,8 @@ public class TextField extends FieldType {
|
|||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean reverse) {
|
||||
/* :TODO: maybe warn if isTokenized(), but doesn't use LimitTokenCountFilter in its chain? */
|
||||
field.checkSortability();
|
||||
return Sorting.getTextSortField(field.getName(), reverse, field.sortMissingLast(), field.sortMissingFirst());
|
||||
return getSortedSetSortField(field, SortedSetSelector.Type.MIN, reverse,
|
||||
SortField.STRING_FIRST, SortField.STRING_LAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -171,50 +171,14 @@ public class TrieField extends NumericFieldType {
|
|||
|
||||
switch (type) {
|
||||
case INTEGER:
|
||||
if( sortMissingLast ) {
|
||||
missingValue = top ? Integer.MIN_VALUE : Integer.MAX_VALUE;
|
||||
}
|
||||
else if( sortMissingFirst ) {
|
||||
missingValue = top ? Integer.MAX_VALUE : Integer.MIN_VALUE;
|
||||
}
|
||||
sf = new SortField( field.getName(), SortField.Type.INT, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
|
||||
return getSortField(field, SortField.Type.INT, top, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||
case FLOAT:
|
||||
if( sortMissingLast ) {
|
||||
missingValue = top ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
|
||||
}
|
||||
else if( sortMissingFirst ) {
|
||||
missingValue = top ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
|
||||
}
|
||||
sf = new SortField( field.getName(), SortField.Type.FLOAT, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
|
||||
return getSortField(field, SortField.Type.FLOAT, top, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
|
||||
case DATE: // fallthrough
|
||||
case LONG:
|
||||
if( sortMissingLast ) {
|
||||
missingValue = top ? Long.MIN_VALUE : Long.MAX_VALUE;
|
||||
}
|
||||
else if( sortMissingFirst ) {
|
||||
missingValue = top ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
sf = new SortField( field.getName(), SortField.Type.LONG, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
|
||||
return getSortField(field, SortField.Type.LONG, top, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||
case DOUBLE:
|
||||
if( sortMissingLast ) {
|
||||
missingValue = top ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
|
||||
}
|
||||
else if( sortMissingFirst ) {
|
||||
missingValue = top ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
sf = new SortField( field.getName(), SortField.Type.DOUBLE, top);
|
||||
sf.setMissingValue(missingValue);
|
||||
return sf;
|
||||
|
||||
return getSortField(field, SortField.Type.DOUBLE, top, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
default:
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + field.name);
|
||||
}
|
||||
|
|
|
@ -16,15 +16,16 @@
|
|||
*/
|
||||
package org.apache.solr.search;
|
||||
|
||||
import org.apache.solr.schema.FieldType;
|
||||
import org.apache.lucene.search.*;
|
||||
|
||||
/**
|
||||
* Extra lucene sorting utilities & convenience methods
|
||||
*
|
||||
*
|
||||
*
|
||||
* @deprecated custom {@link FieldType}s should use the helper methods in the base class. Other usage should leverage th underling lucene {@link SortField} classes directly.
|
||||
*/
|
||||
|
||||
@Deprecated
|
||||
public class Sorting {
|
||||
|
||||
|
||||
|
@ -37,14 +38,19 @@ public class Sorting {
|
|||
* @param nullLast true if null should come last, regardless of sort order
|
||||
* @param nullFirst true if null should come first, regardless of sort order
|
||||
* @return SortField
|
||||
* @deprecated custom {@link FieldType}s should use {@link FieldType#getSortField}. Other usage should leverage th underling lucene {@link SortField} classes directly.
|
||||
*/
|
||||
@Deprecated
|
||||
public static SortField getStringSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) {
|
||||
SortField sortField = new SortField(fieldName, SortField.Type.STRING, reverse);
|
||||
applyMissingFirstLast(sortField, reverse, nullLast, nullFirst);
|
||||
return sortField;
|
||||
}
|
||||
|
||||
/** Like {@link #getStringSortField}) except safe for tokenized fields */
|
||||
/** Like {@link #getStringSortField}) except safe for tokenized fields
|
||||
* @deprecated custom {@link FieldType}s should use {@link FieldType#getSortedSetSortField}. Other usage should leverage th underling lucene {@link SortedSetSortField} classes directly.
|
||||
*/
|
||||
@Deprecated
|
||||
public static SortField getTextSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) {
|
||||
SortField sortField = new SortedSetSortField(fieldName, reverse);
|
||||
applyMissingFirstLast(sortField, reverse, nullLast, nullFirst);
|
||||
|
|
|
@ -18,12 +18,22 @@
|
|||
<schema name="tiny" version="1.1">
|
||||
<field name="id" type="string" indexed="true" stored="true" required="true"/>
|
||||
<field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<!-- Test EnumField and EnumFieldType -->
|
||||
<field name="severity" type="severityType" indexed="${solr.tests.EnumFieldTest.indexed}" stored="true" multiValued="false" docValues="${solr.tests.numeric.dv}"/>
|
||||
<!-- NOTE: because these test sortMissingLast/sortMissingFirst, we force indexed="true" so we don't get
|
||||
random errors on schema init about inconsistent properties -->
|
||||
<field name="severity_missingLast" type="severityType" indexed="true" stored="true" multiValued="false" docValues="${solr.tests.numeric.dv}" sortMissingLast="true"/>
|
||||
<field name="severity_missingFirst" type="severityType" indexed="true" stored="true" multiValued="false" docValues="${solr.tests.numeric.dv}" sortMissingFirst="true"/>
|
||||
|
||||
<field name="severity_mv" type="severityType" indexed="${solr.tests.EnumFieldTest.indexed}" stored="true" multiValued="true" docValues="${solr.tests.numeric.dv}"/>
|
||||
<field name="text" type="text" indexed="true" stored="true" multiValued="true"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
<copyField source="severity" dest="severity_missingLast" />
|
||||
<copyField source="severity" dest="severity_missingFirst" />
|
||||
|
||||
<fieldType name="text" class="solr.TextField">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.apache.solr.schema;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -385,6 +386,21 @@ public class EnumFieldTest extends SolrTestCaseJ4 {
|
|||
"//doc[4]/str[@name='" + FIELD_NAME + "']/text()='High'",
|
||||
"//doc[5]/str[@name='" + FIELD_NAME + "']/text()='Critical'"
|
||||
);
|
||||
|
||||
// missing first....
|
||||
for (String dir : Arrays.asList("asc", "desc")) {
|
||||
assertQ(req("fl", "id", "q", "*:*", "sort", FIELD_NAME + "_missingFirst " + dir + ", id desc")
|
||||
, "//doc[1]/str[@name='id']/text()='9'"
|
||||
, "//doc[2]/str[@name='id']/text()='8'"
|
||||
);
|
||||
}
|
||||
// missing last...
|
||||
for (String dir : Arrays.asList("asc", "desc")) {
|
||||
assertQ(req("fl", "id", "q", "*:*", "sort", FIELD_NAME + "_missingLast " + dir + ", id desc")
|
||||
, "//doc[6]/str[@name='id']/text()='9'"
|
||||
, "//doc[7]/str[@name='id']/text()='8'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -3331,7 +3331,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
|
||||
int numVals = 10 * RANDOM_MULTIPLIER;
|
||||
// Restrict values to float range; otherwise conversion to float will cause truncation -> undefined results
|
||||
List<Double> values = getRandomList(10, false, () -> {
|
||||
List<Double> values = getRandomList(numVals, false, () -> {
|
||||
Float f = Float.NaN;
|
||||
while (f.isNaN()) {
|
||||
f = Float.intBitsToFloat(random().nextInt());
|
||||
|
|
|
@ -271,9 +271,9 @@ public class TestSort extends SolrTestCaseJ4 {
|
|||
|
||||
if (r.nextBoolean()) sfields.add( new SortField(null, SortField.Type.SCORE));
|
||||
// hit both use-cases of sort-missing-last
|
||||
sfields.add( Sorting.getStringSortField("f", reverse, sortMissingLast, sortMissingFirst) );
|
||||
sfields.add( getStringSortField("f", reverse, sortMissingLast, sortMissingFirst) );
|
||||
if (secondary) {
|
||||
sfields.add( Sorting.getStringSortField("f2", reverse2, sortMissingLast2, sortMissingFirst2) );
|
||||
sfields.add( getStringSortField("f2", reverse2, sortMissingLast2, sortMissingFirst2) );
|
||||
}
|
||||
if (r.nextBoolean()) sfields.add( new SortField(null, SortField.Type.SCORE));
|
||||
|
||||
|
@ -355,5 +355,20 @@ public class TestSort extends SolrTestCaseJ4 {
|
|||
return new BitDocIdSet(obs);
|
||||
}
|
||||
|
||||
|
||||
private static SortField getStringSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) {
|
||||
SortField sortField = new SortField(fieldName, SortField.Type.STRING, reverse);
|
||||
|
||||
// 4 cases:
|
||||
// missingFirst / forward: default lucene behavior
|
||||
// missingFirst / reverse: set sortMissingLast
|
||||
// missingLast / forward: set sortMissingLast
|
||||
// missingLast / reverse: default lucene behavior
|
||||
|
||||
if (nullFirst && reverse) {
|
||||
sortField.setMissingValue(SortField.STRING_LAST);
|
||||
} else if (nullLast && !reverse) {
|
||||
sortField.setMissingValue(SortField.STRING_LAST);
|
||||
}
|
||||
return sortField;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.solr.client.solrj.io.eval;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.math3.primes.Primes;
|
||||
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
|
||||
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
|
||||
|
||||
public class PrimesEvaluator extends RecursiveNumericEvaluator implements ManyValueWorker {
|
||||
protected static final long serialVersionUID = 1L;
|
||||
|
||||
public PrimesEvaluator(StreamExpression expression, StreamFactory factory) throws IOException{
|
||||
super(expression, factory);
|
||||
|
||||
if(2 != containedEvaluators.size()){
|
||||
throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression, containedEvaluators.size()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object doWork(Object... values) throws IOException {
|
||||
if(2 != values.length){
|
||||
throw new IOException(String.format(Locale.ROOT,"%s(...) only works with 2 values but %d were provided", constructingFactory.getFunctionName(getClass()), values.length));
|
||||
}
|
||||
|
||||
int sizeNum = ((Number)values[0]).intValue();
|
||||
int startNum = ((Number)values[1]).intValue();
|
||||
List<Number> primes = new ArrayList();
|
||||
|
||||
for(int i=0; i< sizeNum; i++) {
|
||||
int prime = Primes.nextPrime(startNum);
|
||||
primes.add(prime);
|
||||
startNum = prime;
|
||||
++startNum;
|
||||
}
|
||||
|
||||
return primes;
|
||||
}
|
||||
}
|
|
@ -5857,6 +5857,35 @@ public class StreamExpressionTest extends SolrCloudTestCase {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPrimes() throws Exception {
|
||||
String cexpr = "primes(10, 0)";
|
||||
ModifiableSolrParams paramsLoc = new ModifiableSolrParams();
|
||||
paramsLoc.set("expr", cexpr);
|
||||
paramsLoc.set("qt", "/stream");
|
||||
|
||||
String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS;
|
||||
TupleStream solrStream = new SolrStream(url, paramsLoc);
|
||||
|
||||
StreamContext context = new StreamContext();
|
||||
solrStream.setStreamContext(context);
|
||||
List<Tuple> tuples = getTuples(solrStream);
|
||||
assertTrue(tuples.size() == 1);
|
||||
Tuple tuple = tuples.get(0);
|
||||
List<Number> asort = (List<Number>)tuple.get("return-value");
|
||||
assertEquals(asort.size(), 10);
|
||||
assertEquals(asort.get(0).intValue(), 2);
|
||||
assertEquals(asort.get(1).intValue(), 3);
|
||||
assertEquals(asort.get(2).intValue(), 5);
|
||||
assertEquals(asort.get(3).intValue(), 7);
|
||||
assertEquals(asort.get(4).intValue(), 11);
|
||||
assertEquals(asort.get(5).intValue(), 13);
|
||||
assertEquals(asort.get(6).intValue(), 17);
|
||||
assertEquals(asort.get(7).intValue(), 19);
|
||||
assertEquals(asort.get(8).intValue(), 23);
|
||||
assertEquals(asort.get(9).intValue(), 29);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAscend() throws Exception {
|
||||
String cexpr = "asc(array(11.5, 12.3, 4, 3, 1, 0))";
|
||||
|
|
Loading…
Reference in New Issue