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-10101: TestLazyCores hangs (Erick Erickson)
|
||||||
|
|
||||||
|
* SOLR-11332: Fix sorting on 'enum' fieldTypes that use sortMissingFirst or sortMissingLast (hossman)
|
||||||
|
|
||||||
Optimizations
|
Optimizations
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
@ -199,6 +201,10 @@ Other Changes
|
||||||
|
|
||||||
* SOLR-10990: Breakup QueryComponent.process method for readability. (Christine Poerschke)
|
* 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 ==================
|
================== 7.0.0 ==================
|
||||||
|
|
||||||
Versions of Major Components
|
Versions of Major Components
|
||||||
|
|
|
@ -80,7 +80,7 @@ public abstract class LTRScoringModel {
|
||||||
protected final List<Feature> features;
|
protected final List<Feature> features;
|
||||||
private final List<Feature> allFeatures;
|
private final List<Feature> allFeatures;
|
||||||
private final Map<String,Object> params;
|
private final Map<String,Object> params;
|
||||||
private final List<Normalizer> norms;
|
protected final List<Normalizer> norms;
|
||||||
|
|
||||||
public static LTRScoringModel getInstance(SolrResourceLoader solrResourceLoader,
|
public static LTRScoringModel getInstance(SolrResourceLoader solrResourceLoader,
|
||||||
String className, String name, List<Feature> features,
|
String className, String name, List<Feature> features,
|
||||||
|
@ -123,6 +123,8 @@ public abstract class LTRScoringModel {
|
||||||
* {@link ModelException} if they do not make sense.
|
* {@link ModelException} if they do not make sense.
|
||||||
*/
|
*/
|
||||||
protected void validate() throws ModelException {
|
protected void validate() throws ModelException {
|
||||||
|
final List<Feature> features = getFeatures();
|
||||||
|
final List<Normalizer> norms = getNorms();
|
||||||
if (features.isEmpty()) {
|
if (features.isEmpty()) {
|
||||||
throw new ModelException("no features declared for model "+name);
|
throw new ModelException("no features declared for model "+name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,12 +239,14 @@ public class TestRerankBase extends RestTestBase {
|
||||||
.append(",\n");
|
.append(",\n");
|
||||||
sb.append("\"class\":").append('"').append(type).append('"').append(",\n");
|
sb.append("\"class\":").append('"').append(type).append('"').append(",\n");
|
||||||
sb.append("\"features\":").append('[');
|
sb.append("\"features\":").append('[');
|
||||||
for (final String feature : features) {
|
if (features.length > 0) {
|
||||||
sb.append("\n\t{ ");
|
for (final String feature : features) {
|
||||||
sb.append("\"name\":").append('"').append(feature).append('"')
|
sb.append("\n\t{ ");
|
||||||
.append("},");
|
sb.append("\"name\":").append('"').append(feature).append('"')
|
||||||
|
.append("},");
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.length() - 1);
|
||||||
}
|
}
|
||||||
sb.deleteCharAt(sb.length() - 1);
|
|
||||||
sb.append("\n]\n");
|
sb.append("\n]\n");
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
sb.append(",\n");
|
sb.append(",\n");
|
||||||
|
|
|
@ -296,6 +296,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
|
||||||
.withFunctionName("probability", ProbabilityEvaluator.class)
|
.withFunctionName("probability", ProbabilityEvaluator.class)
|
||||||
.withFunctionName("sumDifference", SumDifferenceEvaluator.class)
|
.withFunctionName("sumDifference", SumDifferenceEvaluator.class)
|
||||||
.withFunctionName("meanDifference", MeanDifferenceEvaluator.class)
|
.withFunctionName("meanDifference", MeanDifferenceEvaluator.class)
|
||||||
|
.withFunctionName("primes", PrimesEvaluator.class)
|
||||||
|
|
||||||
// Boolean Stream Evaluators
|
// Boolean Stream Evaluators
|
||||||
|
|
||||||
|
|
|
@ -357,14 +357,14 @@ public class QueryComponent extends SearchComponent
|
||||||
cmd.setSegmentTerminateEarly(false); // not supported, silently ignore any segmentTerminateEarly flag
|
cmd.setSegmentTerminateEarly(false); // not supported, silently ignore any segmentTerminateEarly flag
|
||||||
try {
|
try {
|
||||||
if (params.getBool(GroupParams.GROUP_DISTRIBUTED_FIRST, false)) {
|
if (params.getBool(GroupParams.GROUP_DISTRIBUTED_FIRST, false)) {
|
||||||
doProcessGroupedDistributedSearchFirstPhase(rb, result);
|
doProcessGroupedDistributedSearchFirstPhase(rb, cmd, result);
|
||||||
return;
|
return;
|
||||||
} else if (params.getBool(GroupParams.GROUP_DISTRIBUTED_SECOND, false)) {
|
} else if (params.getBool(GroupParams.GROUP_DISTRIBUTED_SECOND, false)) {
|
||||||
doProcessGroupedDistributedSearchSecondPhase(rb, result);
|
doProcessGroupedDistributedSearchSecondPhase(rb, cmd, result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
doProcessGroupedSearch(rb, result);
|
doProcessGroupedSearch(rb, cmd, result);
|
||||||
return;
|
return;
|
||||||
} catch (SyntaxError e) {
|
} catch (SyntaxError e) {
|
||||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
|
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
|
||||||
|
@ -372,7 +372,7 @@ public class QueryComponent extends SearchComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
// normal search result
|
// normal search result
|
||||||
doProcessUngroupedSearch(rb, result);
|
doProcessUngroupedSearch(rb, cmd, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doFieldSortValues(ResponseBuilder rb, SolrIndexSearcher searcher) throws IOException
|
protected void doFieldSortValues(ResponseBuilder rb, SolrIndexSearcher searcher) throws IOException
|
||||||
|
@ -1248,7 +1248,7 @@ public class QueryComponent extends SearchComponent
|
||||||
return true;
|
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();
|
GroupingSpecification groupingSpec = rb.getGroupingSpec();
|
||||||
assert null != groupingSpec : "GroupingSpecification is null";
|
assert null != groupingSpec : "GroupingSpecification is null";
|
||||||
|
@ -1259,8 +1259,6 @@ public class QueryComponent extends SearchComponent
|
||||||
SolrIndexSearcher searcher = req.getSearcher();
|
SolrIndexSearcher searcher = req.getSearcher();
|
||||||
IndexSchema schema = searcher.getSchema();
|
IndexSchema schema = searcher.getSchema();
|
||||||
|
|
||||||
QueryCommand cmd = rb.getQueryCommand();
|
|
||||||
|
|
||||||
CommandHandler.Builder topsGroupsActionBuilder = new CommandHandler.Builder()
|
CommandHandler.Builder topsGroupsActionBuilder = new CommandHandler.Builder()
|
||||||
.setQueryCommand(cmd)
|
.setQueryCommand(cmd)
|
||||||
.setNeedDocSet(false) // Order matters here
|
.setNeedDocSet(false) // Order matters here
|
||||||
|
@ -1286,7 +1284,7 @@ public class QueryComponent extends SearchComponent
|
||||||
rb.setResult(result);
|
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();
|
GroupingSpecification groupingSpec = rb.getGroupingSpec();
|
||||||
assert null != groupingSpec : "GroupingSpecification is null";
|
assert null != groupingSpec : "GroupingSpecification is null";
|
||||||
|
@ -1299,7 +1297,6 @@ public class QueryComponent extends SearchComponent
|
||||||
SolrIndexSearcher searcher = req.getSearcher();
|
SolrIndexSearcher searcher = req.getSearcher();
|
||||||
IndexSchema schema = searcher.getSchema();
|
IndexSchema schema = searcher.getSchema();
|
||||||
|
|
||||||
QueryCommand cmd = rb.getQueryCommand();
|
|
||||||
boolean needScores = (cmd.getFlags() & SolrIndexSearcher.GET_SCORES) != 0;
|
boolean needScores = (cmd.getFlags() & SolrIndexSearcher.GET_SCORES) != 0;
|
||||||
|
|
||||||
CommandHandler.Builder secondPhaseBuilder = new CommandHandler.Builder()
|
CommandHandler.Builder secondPhaseBuilder = new CommandHandler.Builder()
|
||||||
|
@ -1358,7 +1355,7 @@ public class QueryComponent extends SearchComponent
|
||||||
rb.setResult(result);
|
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();
|
GroupingSpecification groupingSpec = rb.getGroupingSpec();
|
||||||
assert null != groupingSpec : "GroupingSpecification is null";
|
assert null != groupingSpec : "GroupingSpecification is null";
|
||||||
|
@ -1370,8 +1367,6 @@ public class QueryComponent extends SearchComponent
|
||||||
|
|
||||||
SolrIndexSearcher searcher = req.getSearcher();
|
SolrIndexSearcher searcher = req.getSearcher();
|
||||||
|
|
||||||
QueryCommand cmd = rb.getQueryCommand();
|
|
||||||
|
|
||||||
int maxDocsPercentageToCache = params.getInt(GroupParams.GROUP_CACHE_PERCENTAGE, 0);
|
int maxDocsPercentageToCache = params.getInt(GroupParams.GROUP_CACHE_PERCENTAGE, 0);
|
||||||
boolean cacheSecondPassSearch = maxDocsPercentageToCache >= 1 && maxDocsPercentageToCache <= 100;
|
boolean cacheSecondPassSearch = maxDocsPercentageToCache >= 1 && maxDocsPercentageToCache <= 100;
|
||||||
Grouping.TotalCount defaultTotalCount = groupingSpec.isIncludeGroupCount() ?
|
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;
|
SolrQueryRequest req = rb.req;
|
||||||
SolrQueryResponse rsp = rb.rsp;
|
SolrQueryResponse rsp = rb.rsp;
|
||||||
|
|
||||||
SolrIndexSearcher searcher = req.getSearcher();
|
SolrIndexSearcher searcher = req.getSearcher();
|
||||||
|
|
||||||
QueryCommand cmd = rb.getQueryCommand();
|
|
||||||
|
|
||||||
searcher.search(result, cmd);
|
searcher.search(result, cmd);
|
||||||
rb.setResult(result);
|
rb.setResult(result);
|
||||||
|
|
||||||
|
|
|
@ -250,11 +250,12 @@ public abstract class AbstractEnumField extends PrimitiveFieldType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean top) {
|
public SortField getSortField(SchemaField field, boolean top) {
|
||||||
field.checkSortability();
|
SortField result = getSortField(field, SortField.Type.INT, top, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
final Object missingValue = Integer.MIN_VALUE;
|
if (null == result.getMissingValue()) {
|
||||||
SortField sf = new SortField(field.getName(), SortField.Type.INT, top);
|
// special case default behavior: assume missing values are "below" all enum values
|
||||||
sf.setMissingValue(missingValue);
|
result.setMissingValue(Integer.MIN_VALUE);
|
||||||
return sf;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -190,20 +190,7 @@ public class DatePointField extends PointField implements DateValueFieldType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean top) {
|
public SortField getSortField(SchemaField field, boolean top) {
|
||||||
field.checkSortability();
|
return getSortField(field, SortField.Type.LONG, top, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -134,20 +134,7 @@ public class DoublePointField extends PointField implements DoubleValueFieldType
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean top) {
|
public SortField getSortField(SchemaField field, boolean top) {
|
||||||
field.checkSortability();
|
return getSortField(field, SortField.Type.DOUBLE, top, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.apache.lucene.search.MultiTermQuery;
|
||||||
import org.apache.lucene.search.PrefixQuery;
|
import org.apache.lucene.search.PrefixQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.SortField;
|
import org.apache.lucene.search.SortField;
|
||||||
|
import org.apache.lucene.search.SortedSetSortField;
|
||||||
import org.apache.lucene.search.SortedNumericSelector;
|
import org.apache.lucene.search.SortedNumericSelector;
|
||||||
import org.apache.lucene.search.SortedSetSelector;
|
import org.apache.lucene.search.SortedSetSelector;
|
||||||
import org.apache.lucene.search.TermInSetQuery;
|
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.response.TextResponseWriter;
|
||||||
import org.apache.solr.search.QParser;
|
import org.apache.solr.search.QParser;
|
||||||
import org.apache.solr.search.QueryUtils;
|
import org.apache.solr.search.QueryUtils;
|
||||||
import org.apache.solr.search.Sorting;
|
|
||||||
import org.apache.solr.uninverting.UninvertingReader;
|
import org.apache.solr.uninverting.UninvertingReader;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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
|
* Returns the SortField instance that should be used to sort fields
|
||||||
* of this type.
|
* of this type.
|
||||||
* @see SchemaField#checkSortability
|
* @see SchemaField#checkSortability
|
||||||
|
* @see #getSortField(SchemaField,SortField.Type,boolean,Object,Object)
|
||||||
*/
|
*/
|
||||||
public abstract SortField getSortField(SchemaField field, boolean top);
|
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
|
* Utility usable by subclasses when they want to get basic String sorting
|
||||||
* using common checks.
|
* using common checks.
|
||||||
* @see SchemaField#checkSortability
|
* @see SchemaField#checkSortability
|
||||||
*/
|
*/
|
||||||
protected SortField getStringSort(SchemaField field, boolean reverse) {
|
protected SortField getStringSort(SchemaField field, boolean reverse) {
|
||||||
field.checkSortability();
|
return getSortField(field, SortField.Type.STRING, reverse, SortField.STRING_FIRST, SortField.STRING_LAST);
|
||||||
return Sorting.getStringSortField(field.name, reverse, field.sortMissingLast(),field.sortMissingFirst());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** called to get the default value source (normally, from the
|
/** called to get the default value source (normally, from the
|
||||||
|
|
|
@ -134,20 +134,7 @@ public class FloatPointField extends PointField implements FloatValueFieldType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean top) {
|
public SortField getSortField(SchemaField field, boolean top) {
|
||||||
field.checkSortability();
|
return getSortField(field, SortField.Type.FLOAT, top, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -132,20 +132,7 @@ public class IntPointField extends PointField implements IntValueFieldType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean top) {
|
public SortField getSortField(SchemaField field, boolean top) {
|
||||||
field.checkSortability();
|
return getSortField(field, SortField.Type.INT, top, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -131,20 +131,7 @@ public class LongPointField extends PointField implements LongValueFieldType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean top) {
|
public SortField getSortField(SchemaField field, boolean top) {
|
||||||
field.checkSortability();
|
return getSortField(field, SortField.Type.LONG, top, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
||||||
import org.apache.lucene.queries.function.valuesource.SortedSetFieldSource;
|
import org.apache.lucene.queries.function.valuesource.SortedSetFieldSource;
|
||||||
import org.apache.lucene.search.SortField;
|
import org.apache.lucene.search.SortField;
|
||||||
|
import org.apache.lucene.search.SortedSetSelector;
|
||||||
import org.apache.lucene.util.AttributeFactory;
|
import org.apache.lucene.util.AttributeFactory;
|
||||||
import org.apache.lucene.util.AttributeSource.State;
|
import org.apache.lucene.util.AttributeSource.State;
|
||||||
import org.apache.lucene.util.AttributeSource;
|
import org.apache.lucene.util.AttributeSource;
|
||||||
import org.apache.solr.analysis.SolrAnalyzer;
|
import org.apache.solr.analysis.SolrAnalyzer;
|
||||||
import org.apache.solr.response.TextResponseWriter;
|
import org.apache.solr.response.TextResponseWriter;
|
||||||
import org.apache.solr.search.QParser;
|
import org.apache.solr.search.QParser;
|
||||||
import org.apache.solr.search.Sorting;
|
|
||||||
import org.apache.solr.uninverting.UninvertingReader.Type;
|
import org.apache.solr.uninverting.UninvertingReader.Type;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -132,8 +132,8 @@ public class PreAnalyzedField extends TextField implements HasImplicitIndexAnaly
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean top) {
|
public SortField getSortField(SchemaField field, boolean top) {
|
||||||
field.checkSortability();
|
return getSortedSetSortField(field, SortedSetSelector.Type.MIN, top,
|
||||||
return Sorting.getTextSortField(field.getName(), top, field.sortMissingLast(), field.sortMissingFirst());
|
SortField.STRING_FIRST, SortField.STRING_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.apache.solr.common.SolrException;
|
||||||
import org.apache.solr.query.SolrRangeQuery;
|
import org.apache.solr.query.SolrRangeQuery;
|
||||||
import org.apache.solr.response.TextResponseWriter;
|
import org.apache.solr.response.TextResponseWriter;
|
||||||
import org.apache.solr.search.QParser;
|
import org.apache.solr.search.QParser;
|
||||||
import org.apache.solr.search.Sorting;
|
|
||||||
import org.apache.solr.uninverting.UninvertingReader.Type;
|
import org.apache.solr.uninverting.UninvertingReader.Type;
|
||||||
|
|
||||||
/** <code>TextField</code> is the basic type for configurable text analysis.
|
/** <code>TextField</code> is the basic type for configurable text analysis.
|
||||||
|
@ -108,8 +107,8 @@ public class TextField extends FieldType {
|
||||||
@Override
|
@Override
|
||||||
public SortField getSortField(SchemaField field, boolean reverse) {
|
public SortField getSortField(SchemaField field, boolean reverse) {
|
||||||
/* :TODO: maybe warn if isTokenized(), but doesn't use LimitTokenCountFilter in its chain? */
|
/* :TODO: maybe warn if isTokenized(), but doesn't use LimitTokenCountFilter in its chain? */
|
||||||
field.checkSortability();
|
return getSortedSetSortField(field, SortedSetSelector.Type.MIN, reverse,
|
||||||
return Sorting.getTextSortField(field.getName(), reverse, field.sortMissingLast(), field.sortMissingFirst());
|
SortField.STRING_FIRST, SortField.STRING_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -171,50 +171,14 @@ public class TrieField extends NumericFieldType {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
if( sortMissingLast ) {
|
return getSortField(field, SortField.Type.INT, top, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
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;
|
|
||||||
|
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
if( sortMissingLast ) {
|
return getSortField(field, SortField.Type.FLOAT, top, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
|
||||||
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;
|
|
||||||
|
|
||||||
case DATE: // fallthrough
|
case DATE: // fallthrough
|
||||||
case LONG:
|
case LONG:
|
||||||
if( sortMissingLast ) {
|
return getSortField(field, SortField.Type.LONG, top, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||||
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;
|
|
||||||
|
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
if( sortMissingLast ) {
|
return getSortField(field, SortField.Type.DOUBLE, top, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||||
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;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + field.name);
|
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + field.name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,16 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.solr.search;
|
package org.apache.solr.search;
|
||||||
|
|
||||||
|
import org.apache.solr.schema.FieldType;
|
||||||
import org.apache.lucene.search.*;
|
import org.apache.lucene.search.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extra lucene sorting utilities & convenience methods
|
* 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 {
|
public class Sorting {
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,14 +38,19 @@ public class Sorting {
|
||||||
* @param nullLast true if null should come last, regardless of sort order
|
* @param nullLast true if null should come last, regardless of sort order
|
||||||
* @param nullFirst true if null should come first, regardless of sort order
|
* @param nullFirst true if null should come first, regardless of sort order
|
||||||
* @return SortField
|
* @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) {
|
public static SortField getStringSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) {
|
||||||
SortField sortField = new SortField(fieldName, SortField.Type.STRING, reverse);
|
SortField sortField = new SortField(fieldName, SortField.Type.STRING, reverse);
|
||||||
applyMissingFirstLast(sortField, reverse, nullLast, nullFirst);
|
applyMissingFirstLast(sortField, reverse, nullLast, nullFirst);
|
||||||
return sortField;
|
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) {
|
public static SortField getTextSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) {
|
||||||
SortField sortField = new SortedSetSortField(fieldName, reverse);
|
SortField sortField = new SortedSetSortField(fieldName, reverse);
|
||||||
applyMissingFirstLast(sortField, reverse, nullLast, nullFirst);
|
applyMissingFirstLast(sortField, reverse, nullLast, nullFirst);
|
||||||
|
|
|
@ -18,12 +18,22 @@
|
||||||
<schema name="tiny" version="1.1">
|
<schema name="tiny" version="1.1">
|
||||||
<field name="id" type="string" indexed="true" stored="true" required="true"/>
|
<field name="id" type="string" indexed="true" stored="true" required="true"/>
|
||||||
<field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>
|
<field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>
|
||||||
|
|
||||||
<!-- Test EnumField and EnumFieldType -->
|
<!-- Test EnumField and EnumFieldType -->
|
||||||
<field name="severity" type="severityType" indexed="${solr.tests.EnumFieldTest.indexed}" stored="true" multiValued="false" docValues="${solr.tests.numeric.dv}"/>
|
<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="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"/>
|
<field name="text" type="text" indexed="true" stored="true" multiValued="true"/>
|
||||||
|
|
||||||
<uniqueKey>id</uniqueKey>
|
<uniqueKey>id</uniqueKey>
|
||||||
|
|
||||||
|
<copyField source="severity" dest="severity_missingLast" />
|
||||||
|
<copyField source="severity" dest="severity_missingFirst" />
|
||||||
|
|
||||||
<fieldType name="text" class="solr.TextField">
|
<fieldType name="text" class="solr.TextField">
|
||||||
<analyzer>
|
<analyzer>
|
||||||
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
|
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.solr.schema;
|
package org.apache.solr.schema;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -385,6 +386,21 @@ public class EnumFieldTest extends SolrTestCaseJ4 {
|
||||||
"//doc[4]/str[@name='" + FIELD_NAME + "']/text()='High'",
|
"//doc[4]/str[@name='" + FIELD_NAME + "']/text()='High'",
|
||||||
"//doc[5]/str[@name='" + FIELD_NAME + "']/text()='Critical'"
|
"//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
|
@Test
|
||||||
|
|
|
@ -3331,7 +3331,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
||||||
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
|
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
|
||||||
int numVals = 10 * RANDOM_MULTIPLIER;
|
int numVals = 10 * RANDOM_MULTIPLIER;
|
||||||
// Restrict values to float range; otherwise conversion to float will cause truncation -> undefined results
|
// 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;
|
Float f = Float.NaN;
|
||||||
while (f.isNaN()) {
|
while (f.isNaN()) {
|
||||||
f = Float.intBitsToFloat(random().nextInt());
|
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));
|
if (r.nextBoolean()) sfields.add( new SortField(null, SortField.Type.SCORE));
|
||||||
// hit both use-cases of sort-missing-last
|
// 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) {
|
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));
|
if (r.nextBoolean()) sfields.add( new SortField(null, SortField.Type.SCORE));
|
||||||
|
|
||||||
|
@ -355,5 +355,20 @@ public class TestSort extends SolrTestCaseJ4 {
|
||||||
return new BitDocIdSet(obs);
|
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
|
@Test
|
||||||
public void testAscend() throws Exception {
|
public void testAscend() throws Exception {
|
||||||
String cexpr = "asc(array(11.5, 12.3, 4, 3, 1, 0))";
|
String cexpr = "asc(array(11.5, 12.3, 4, 3, 1, 0))";
|
||||||
|
|
Loading…
Reference in New Issue