mirror of https://github.com/apache/lucene.git
SOLR-5354: applying hoss's patch to fix function edge case in distributed sort
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1547430 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e8237d6a7a
commit
dff3579da3
|
@ -190,7 +190,7 @@ public class QueryComponent extends SearchComponent
|
|||
// groupSort defaults to sort
|
||||
String groupSortStr = params.get(GroupParams.GROUP_SORT);
|
||||
//TODO: move weighting of sort
|
||||
Sort sortWithinGroup = groupSortStr == null ? groupSort : searcher.weightSort(QueryParsing.parseSort(groupSortStr, req));
|
||||
Sort sortWithinGroup = groupSortStr == null ? groupSort : searcher.weightSort(QueryParsing.parseSortSpec(groupSortStr, req).getSort());
|
||||
if (sortWithinGroup == null) {
|
||||
sortWithinGroup = Sort.RELEVANCE;
|
||||
}
|
||||
|
@ -454,8 +454,6 @@ public class QueryComponent extends SearchComponent
|
|||
// take the documents given and re-derive the sort values.
|
||||
boolean fsv = req.getParams().getBool(ResponseBuilder.FIELD_SORT_VALUES,false);
|
||||
if(fsv){
|
||||
Sort sort = searcher.weightSort(rb.getSortSpec().getSort());
|
||||
SortField[] sortFields = sort==null ? new SortField[]{SortField.FIELD_SCORE} : sort.getSort();
|
||||
NamedList<Object[]> sortVals = new NamedList<Object[]>(); // order is important for the sort fields
|
||||
IndexReaderContext topReaderContext = searcher.getTopReaderContext();
|
||||
List<AtomicReaderContext> leaves = topReaderContext.leaves();
|
||||
|
@ -477,19 +475,23 @@ public class QueryComponent extends SearchComponent
|
|||
}
|
||||
Arrays.sort(sortedIds);
|
||||
|
||||
SortSpec sortSpec = rb.getSortSpec();
|
||||
Sort sort = searcher.weightSort(sortSpec.getSort());
|
||||
SortField[] sortFields = sort==null ? new SortField[]{SortField.FIELD_SCORE} : sort.getSort();
|
||||
List<SchemaField> schemaFields = sortSpec.getSchemaFields();
|
||||
|
||||
for (int fld = 0; fld < schemaFields.size(); fld++) {
|
||||
SchemaField schemaField = schemaFields.get(fld);
|
||||
FieldType ft = null == schemaField? null : schemaField.getType();
|
||||
SortField sortField = sortFields[fld];
|
||||
|
||||
for (SortField sortField: sortFields) {
|
||||
SortField.Type type = sortField.getType();
|
||||
// :TODO: would be simpler to always serialize every position of SortField[]
|
||||
if (type==SortField.Type.SCORE || type==SortField.Type.DOC) continue;
|
||||
|
||||
FieldComparator comparator = null;
|
||||
|
||||
String fieldname = sortField.getField();
|
||||
FieldType ft = fieldname==null ? null : searcher.getSchema().getFieldTypeNoEx(fieldname);
|
||||
|
||||
Object[] vals = new Object[nDocs];
|
||||
|
||||
|
||||
int lastIdx = -1;
|
||||
int idx = 0;
|
||||
|
||||
|
@ -518,7 +520,7 @@ public class QueryComponent extends SearchComponent
|
|||
vals[position] = val;
|
||||
}
|
||||
|
||||
sortVals.add(fieldname, vals);
|
||||
sortVals.add(sortField.getField(), vals);
|
||||
}
|
||||
|
||||
rsp.add("sort_values", sortVals);
|
||||
|
@ -865,7 +867,7 @@ public class QueryComponent extends SearchComponent
|
|||
}
|
||||
}
|
||||
|
||||
shardDoc.sortFieldValues = unmarshalSortValues(sortFieldValues, schema);
|
||||
shardDoc.sortFieldValues = unmarshalSortValues(ss, sortFieldValues, schema);
|
||||
|
||||
queue.insertWithOverflow(shardDoc);
|
||||
} // end for-each-doc-in-response
|
||||
|
@ -907,22 +909,43 @@ public class QueryComponent extends SearchComponent
|
|||
}
|
||||
}
|
||||
|
||||
private NamedList unmarshalSortValues(NamedList sortFieldValues, IndexSchema schema) {
|
||||
private NamedList unmarshalSortValues(SortSpec sortSpec,
|
||||
NamedList sortFieldValues,
|
||||
IndexSchema schema) {
|
||||
NamedList unmarshalledSortValsPerField = new NamedList();
|
||||
for (int fieldNum = 0 ; fieldNum < sortFieldValues.size() ; ++fieldNum) {
|
||||
String fieldName = sortFieldValues.getName(fieldNum);
|
||||
SchemaField field = schema.getFieldOrNull(fieldName);
|
||||
List sortVals = (List)sortFieldValues.getVal(fieldNum);
|
||||
if (null == field) {
|
||||
unmarshalledSortValsPerField.add(fieldName, sortVals);
|
||||
|
||||
if (0 == sortFieldValues.size()) return unmarshalledSortValsPerField;
|
||||
|
||||
List<SchemaField> schemaFields = sortSpec.getSchemaFields();
|
||||
SortField[] sortFields = sortSpec.getSort().getSort();
|
||||
|
||||
int marshalledFieldNum = 0;
|
||||
for (int sortFieldNum = 0; sortFieldNum < sortFields.length; sortFieldNum++) {
|
||||
final SortField sortField = sortFields[sortFieldNum];
|
||||
final SortField.Type type = sortField.getType();
|
||||
|
||||
// :TODO: would be simpler to always serialize every position of SortField[]
|
||||
if (type==SortField.Type.SCORE || type==SortField.Type.DOC) continue;
|
||||
|
||||
final String sortFieldName = sortField.getField();
|
||||
final String valueFieldName = sortFieldValues.getName(marshalledFieldNum);
|
||||
assert sortFieldName.equals(valueFieldName)
|
||||
: "sortFieldValues name key does not match expected SortField.getField";
|
||||
|
||||
List sortVals = (List)sortFieldValues.getVal(marshalledFieldNum);
|
||||
|
||||
final SchemaField schemaField = schemaFields.get(sortFieldNum);
|
||||
if (null == schemaField) {
|
||||
unmarshalledSortValsPerField.add(sortField.getField(), sortVals);
|
||||
} else {
|
||||
FieldType fieldType = field.getType();
|
||||
FieldType fieldType = schemaField.getType();
|
||||
List unmarshalledSortVals = new ArrayList();
|
||||
for (Object sortVal : sortVals) {
|
||||
unmarshalledSortVals.add(fieldType.unmarshalSortValue(sortVal));
|
||||
}
|
||||
unmarshalledSortValsPerField.add(fieldName, unmarshalledSortVals);
|
||||
unmarshalledSortValsPerField.add(sortField.getField(), unmarshalledSortVals);
|
||||
}
|
||||
marshalledFieldNum++;
|
||||
}
|
||||
return unmarshalledSortValsPerField;
|
||||
}
|
||||
|
|
|
@ -419,16 +419,16 @@ public class QueryElevationComponent extends SearchComponent implements SolrCore
|
|||
// insert documents in their proper place
|
||||
SortSpec sortSpec = rb.getSortSpec();
|
||||
if (sortSpec.getSort() == null) {
|
||||
sortSpec.setSort(new Sort(new SortField[]{
|
||||
sortSpec.setSortAndFields(new Sort(new SortField[]{
|
||||
new SortField("_elevate_", comparator, true),
|
||||
new SortField(null, SortField.Type.SCORE, false)
|
||||
}));
|
||||
}),
|
||||
Arrays.asList(new SchemaField[2]));
|
||||
} else {
|
||||
// Check if the sort is based on score
|
||||
SortField[] current = sortSpec.getSort().getSort();
|
||||
Sort modified = this.modifySort(current, force, comparator);
|
||||
if(modified != null) {
|
||||
sortSpec.setSort(modified);
|
||||
SortSpec modSortSpec = this.modifySortSpec(sortSpec, force, comparator);
|
||||
if (null != modSortSpec) {
|
||||
rb.setSortSpec(modSortSpec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,22 +470,43 @@ public class QueryElevationComponent extends SearchComponent implements SolrCore
|
|||
}
|
||||
|
||||
private Sort modifySort(SortField[] current, boolean force, ElevationComparatorSource comparator) {
|
||||
SortSpec tmp = new SortSpec(new Sort(current), Arrays.asList(new SchemaField[current.length]));
|
||||
tmp = modifySortSpec(tmp, force, comparator);
|
||||
return null == tmp ? null : tmp.getSort();
|
||||
}
|
||||
|
||||
private SortSpec modifySortSpec(SortSpec current, boolean force, ElevationComparatorSource comparator) {
|
||||
boolean modify = false;
|
||||
ArrayList<SortField> sorts = new ArrayList<SortField>(current.length + 1);
|
||||
SortField[] currentSorts = current.getSort().getSort();
|
||||
List<SchemaField> currentFields = current.getSchemaFields();
|
||||
|
||||
ArrayList<SortField> sorts = new ArrayList<SortField>(currentSorts.length + 1);
|
||||
List<SchemaField> fields = new ArrayList<SchemaField>(currentFields.size() + 1);
|
||||
|
||||
// Perhaps force it to always sort by score
|
||||
if (force && current[0].getType() != SortField.Type.SCORE) {
|
||||
if (force && currentSorts[0].getType() != SortField.Type.SCORE) {
|
||||
sorts.add(new SortField("_elevate_", comparator, true));
|
||||
fields.add(null);
|
||||
modify = true;
|
||||
}
|
||||
for (SortField sf : current) {
|
||||
for (int i = 0; i < currentSorts.length; i++) {
|
||||
SortField sf = currentSorts[i];
|
||||
if (sf.getType() == SortField.Type.SCORE) {
|
||||
sorts.add(new SortField("_elevate_", comparator, !sf.getReverse()));
|
||||
fields.add(null);
|
||||
modify = true;
|
||||
}
|
||||
sorts.add(sf);
|
||||
fields.add(currentFields.get(i));
|
||||
}
|
||||
|
||||
return modify ? new Sort(sorts.toArray(new SortField[sorts.size()])) : null;
|
||||
if (modify) {
|
||||
SortSpec newSpec = new SortSpec(new Sort(sorts.toArray(new SortField[sorts.size()])),
|
||||
fields);
|
||||
newSpec.setOffset(current.getOffset());
|
||||
newSpec.setCount(current.getCount());
|
||||
return newSpec;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -86,9 +86,9 @@ class OldLuceneQParser extends LuceneQParser {
|
|||
public SortSpec getSort(boolean useGlobal) throws SyntaxError {
|
||||
SortSpec sort = super.getSort(useGlobal);
|
||||
if (sortStr != null && sortStr.length()>0 && sort.getSort()==null) {
|
||||
Sort oldSort = QueryParsing.parseSort(sortStr, getReq());
|
||||
if( oldSort != null ) {
|
||||
sort.sort = oldSort;
|
||||
SortSpec oldSort = QueryParsing.parseSortSpec(sortStr, getReq());
|
||||
if( oldSort.getSort() != null ) {
|
||||
sort.setSortAndFields(oldSort.getSort(), oldSort.getSchemaFields());
|
||||
}
|
||||
}
|
||||
return sort;
|
||||
|
|
|
@ -276,11 +276,11 @@ public abstract class QParser {
|
|||
int start = startS != null ? Integer.parseInt(startS) : 0;
|
||||
int rows = rowsS != null ? Integer.parseInt(rowsS) : 10;
|
||||
|
||||
Sort sort = null;
|
||||
if( sortStr != null ) {
|
||||
sort = QueryParsing.parseSort(sortStr, req);
|
||||
}
|
||||
return new SortSpec( sort, start, rows );
|
||||
SortSpec sort = QueryParsing.parseSortSpec(sortStr, req);
|
||||
|
||||
sort.setOffset(start);
|
||||
sort.setCount(rows);
|
||||
return sort;
|
||||
}
|
||||
|
||||
public String[] getDefaultHighlightFields() {
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.apache.solr.schema.FieldType;
|
|||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -219,16 +220,24 @@ public class QueryParsing {
|
|||
return new MapSolrParams(localParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Sort object represented by the string, or null if default sort
|
||||
* by score descending should be used.
|
||||
* @see #parseSortSpec
|
||||
* @deprecated use {@link #parseSortSpec}
|
||||
*/
|
||||
@Deprecated
|
||||
public static Sort parseSort(String sortSpec, SolrQueryRequest req) {
|
||||
return parseSortSpec(sortSpec, req).getSort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null if the sortSpec is the standard sort desc.
|
||||
* <p/>
|
||||
* <p>
|
||||
* The form of the sort specification string currently parsed is:
|
||||
* </p>
|
||||
* <pre>
|
||||
* SortSpec ::= SingleSort [, SingleSort]*
|
||||
* SingleSort ::= <fieldname> SortDirection
|
||||
* SingleSort ::= <fieldname|function> SortDirection
|
||||
* SortDirection ::= top | desc | bottom | asc
|
||||
* </pre>
|
||||
* Examples:
|
||||
|
@ -239,10 +248,15 @@ public class QueryParsing {
|
|||
* height desc,weight desc #sort by height descending, and use weight descending to break any ties
|
||||
* height desc,weight asc #sort by height descending, using weight ascending as a tiebreaker
|
||||
* </pre>
|
||||
* @return a SortSpec object populated with the appropriate Sort (which may be null if
|
||||
* default score sort is used) and SchemaFields (where applicable) using
|
||||
* hardcoded default count & offset values.
|
||||
*/
|
||||
public static Sort parseSort(String sortSpec, SolrQueryRequest req) {
|
||||
if (sortSpec == null || sortSpec.length() == 0) return null;
|
||||
List<SortField> lst = new ArrayList<SortField>(4);
|
||||
public static SortSpec parseSortSpec(String sortSpec, SolrQueryRequest req) {
|
||||
if (sortSpec == null || sortSpec.length() == 0) return newEmptySortSpec();
|
||||
|
||||
List<SortField> sorts = new ArrayList<SortField>(4);
|
||||
List<SchemaField> fields = new ArrayList<SchemaField>(4);
|
||||
|
||||
try {
|
||||
|
||||
|
@ -299,10 +313,11 @@ public class QueryParsing {
|
|||
if (null != top) {
|
||||
// we have a Query and a valid direction
|
||||
if (q instanceof FunctionQuery) {
|
||||
lst.add(((FunctionQuery)q).getValueSource().getSortField(top));
|
||||
sorts.add(((FunctionQuery)q).getValueSource().getSortField(top));
|
||||
} else {
|
||||
lst.add((new QueryValueSource(q, 0.0f)).getSortField(top));
|
||||
sorts.add((new QueryValueSource(q, 0.0f)).getSortField(top));
|
||||
}
|
||||
fields.add(null);
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -327,12 +342,14 @@ public class QueryParsing {
|
|||
|
||||
if (SCORE.equals(field)) {
|
||||
if (top) {
|
||||
lst.add(SortField.FIELD_SCORE);
|
||||
sorts.add(SortField.FIELD_SCORE);
|
||||
} else {
|
||||
lst.add(new SortField(null, SortField.Type.SCORE, true));
|
||||
sorts.add(new SortField(null, SortField.Type.SCORE, true));
|
||||
}
|
||||
fields.add(null);
|
||||
} else if (DOCID.equals(field)) {
|
||||
lst.add(new SortField(null, SortField.Type.DOC, top));
|
||||
sorts.add(new SortField(null, SortField.Type.DOC, top));
|
||||
fields.add(null);
|
||||
} else {
|
||||
// try to find the field
|
||||
SchemaField sf = req.getSchema().getFieldOrNull(field);
|
||||
|
@ -348,7 +365,8 @@ public class QueryParsing {
|
|||
(SolrException.ErrorCode.BAD_REQUEST,
|
||||
"sort param field can't be found: " + field);
|
||||
}
|
||||
lst.add(sf.getSortField(top));
|
||||
sorts.add(sf.getSortField(top));
|
||||
fields.add(sf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,13 +376,17 @@ public class QueryParsing {
|
|||
|
||||
|
||||
// normalize a sort on score desc to null
|
||||
if (lst.size()==1 && lst.get(0) == SortField.FIELD_SCORE) {
|
||||
return null;
|
||||
if (sorts.size()==1 && sorts.get(0) == SortField.FIELD_SCORE) {
|
||||
return newEmptySortSpec();
|
||||
}
|
||||
|
||||
return new Sort(lst.toArray(new SortField[lst.size()]));
|
||||
Sort s = new Sort(sorts.toArray(new SortField[sorts.size()]));
|
||||
return new SortSpec(s, fields);
|
||||
}
|
||||
|
||||
private static SortSpec newEmptySortSpec() {
|
||||
return new SortSpec(null, Collections.<SchemaField>emptyList());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
|
|
|
@ -20,29 +20,63 @@ package org.apache.solr.search;
|
|||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.SortField;
|
||||
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
/***
|
||||
* SortSpec encapsulates a Lucene Sort and a count of the number of documents
|
||||
* to return.
|
||||
*/
|
||||
public class SortSpec
|
||||
{
|
||||
Sort sort;
|
||||
int num;
|
||||
int offset;
|
||||
private Sort sort;
|
||||
private List<SchemaField> fields;
|
||||
private int num = 10;
|
||||
private int offset = 0;
|
||||
|
||||
public SortSpec(Sort sort, List<SchemaField> fields) {
|
||||
setSortAndFields(sort, fields);
|
||||
}
|
||||
public SortSpec(Sort sort, SchemaField[] fields) {
|
||||
setSortAndFields(sort, Arrays.asList(fields));
|
||||
}
|
||||
|
||||
/** @deprecated Specify both Sort and SchemaField[] when constructing */
|
||||
@Deprecated
|
||||
public SortSpec(Sort sort, int num) {
|
||||
this(sort,0,num);
|
||||
}
|
||||
|
||||
/** @deprecated Specify both Sort and SchemaField[] when constructing */
|
||||
@Deprecated
|
||||
public SortSpec(Sort sort, int offset, int num) {
|
||||
this.sort=sort;
|
||||
setSort(sort);
|
||||
this.offset=offset;
|
||||
this.num=num;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #setSortAndFields} */
|
||||
@Deprecated
|
||||
public void setSort( Sort s )
|
||||
{
|
||||
sort = s;
|
||||
fields = Collections.unmodifiableList(Arrays.asList(new SchemaField[s.getSort().length]));
|
||||
}
|
||||
|
||||
/**
|
||||
* the specified SchemaFields must correspond one to one with the Sort's SortFields,
|
||||
* using null where appropriate.
|
||||
*/
|
||||
public void setSortAndFields( Sort s, List<SchemaField> fields )
|
||||
{
|
||||
|
||||
assert null == s || s.getSort().length == fields.size()
|
||||
: "SortFields and SchemaFields do not have equal lengths";
|
||||
this.sort = s;
|
||||
this.fields = Collections.unmodifiableList(fields);
|
||||
}
|
||||
|
||||
public static boolean includesScore(Sort sort) {
|
||||
|
@ -63,10 +97,20 @@ public class SortSpec
|
|||
*/
|
||||
public Sort getSort() { return sort; }
|
||||
|
||||
/**
|
||||
* Gets the Solr SchemaFields that correspond to each of the SortFields used
|
||||
* in this sort. The array may contain null if a SortField doesn't correspond directly
|
||||
* to a SchemaField (ie: score, lucene docid, custom function sorting, etc...)
|
||||
*
|
||||
* @return an immutable list, may be empty if getSort is null
|
||||
*/
|
||||
public List<SchemaField> getSchemaFields() { return fields; }
|
||||
|
||||
/**
|
||||
* Offset into the list of results.
|
||||
*/
|
||||
public int getOffset() { return offset; }
|
||||
public void setOffset(int offset) { this.offset = offset; }
|
||||
|
||||
/**
|
||||
* Gets the number of documents to return after sorting.
|
||||
|
@ -74,6 +118,7 @@ public class SortSpec
|
|||
* @return number of docs to return, or -1 for no cut off (just sort)
|
||||
*/
|
||||
public int getCount() { return num; }
|
||||
public void setCount(int count) { this.num = count; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
|
|
@ -430,7 +430,7 @@ public class SolrPluginUtils {
|
|||
// we can use the Lucene sort ability.
|
||||
Sort sort = null;
|
||||
if (commands.size() >= 2) {
|
||||
sort = QueryParsing.parseSort(commands.get(1), req);
|
||||
sort = QueryParsing.parseSortSpec(commands.get(1), req).getSort();
|
||||
}
|
||||
|
||||
DocList results = req.getSearcher().getDocList(query,(DocSet)null, sort, start, limit);
|
||||
|
@ -825,7 +825,7 @@ public class SolrPluginUtils {
|
|||
SolrException sortE = null;
|
||||
Sort ss = null;
|
||||
try {
|
||||
ss = QueryParsing.parseSort(sort, req);
|
||||
ss = QueryParsing.parseSortSpec(sort, req).getSort();
|
||||
} catch (SolrException e) {
|
||||
sortE = e;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
<field name="payload" type="sortable_binary" indexed="false"
|
||||
stored="true" multiValued="false" docValues="true" required="true"/>
|
||||
<dynamicField name="*_sS" type="string" indexed="false" stored="true"/>
|
||||
|
||||
<!-- catchall wildcard to help ensure we aren't breaking function sorting -->
|
||||
<dynamicField name="*" type="string" indexed="true" stored="true"/>
|
||||
</fields>
|
||||
<defaultSearchField>text</defaultSearchField>
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
|
|
@ -47,7 +47,9 @@ public class DistributedQueryComponentCustomSortTest extends BaseDistributedSear
|
|||
public void doTest() throws Exception {
|
||||
del("*:*");
|
||||
|
||||
index(id, "1", "text", "a", "payload", ByteBuffer.wrap(new byte[] { 0x12, 0x62, 0x15 })); // 2
|
||||
index(id, "1", "text", "a", "payload", ByteBuffer.wrap(new byte[] { 0x12, 0x62, 0x15 }), // 2
|
||||
// quick check to prove "*" dynamicField hasn't been broken by somebody mucking with schema
|
||||
"asdfasdf_field_should_match_catchall_dynamic_field_adsfasdf", "value");
|
||||
index(id, "2", "text", "b", "payload", ByteBuffer.wrap(new byte[] { 0x25, 0x21, 0x16 })); // 5
|
||||
index(id, "3", "text", "a", "payload", ByteBuffer.wrap(new byte[] { 0x35, 0x32, 0x58 })); // 8
|
||||
index(id, "4", "text", "b", "payload", ByteBuffer.wrap(new byte[] { 0x25, 0x21, 0x15 })); // 4
|
||||
|
@ -90,6 +92,10 @@ public class DistributedQueryComponentCustomSortTest extends BaseDistributedSear
|
|||
rsp = query("q", "text:d", "fl", "id", "sort", "payload desc", "rows", "20");
|
||||
assertFieldValues(rsp.getResults(), id, 11, 13, 12);
|
||||
|
||||
// sanity check function sorting
|
||||
rsp = query("q", "id:[1 TO 10]", "fl", "id", "rows", "20",
|
||||
"sort", "abs(sub(5,id)) asc, id desc");
|
||||
assertFieldValues(rsp.getResults(), id, 5 , 6,4 , 7,3 , 8,2 , 9,1 , 10 );
|
||||
|
||||
// Add two more docs with same payload as in doc #4
|
||||
index(id, "14", "text", "b", "payload", ByteBuffer.wrap(new byte[] { 0x25, 0x21, 0x15 }));
|
||||
|
|
|
@ -20,11 +20,15 @@ import org.apache.lucene.search.Query;
|
|||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.SortSpec;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
|
@ -72,22 +76,48 @@ public class QueryParsingTest extends SolrTestCaseJ4 {
|
|||
@Test
|
||||
public void testSort() throws Exception {
|
||||
Sort sort;
|
||||
SortSpec spec;
|
||||
SolrQueryRequest req = req();
|
||||
|
||||
sort = QueryParsing.parseSort("score desc", req);
|
||||
assertNull("sort", sort);//only 1 thing in the list, no Sort specified
|
||||
|
||||
spec = QueryParsing.parseSortSpec("score desc", req);
|
||||
assertNotNull("spec", spec);
|
||||
assertNull(spec.getSort());
|
||||
assertNotNull(spec.getSchemaFields());
|
||||
assertEquals(0, spec.getSchemaFields().size());
|
||||
|
||||
// SOLR-4458 - using different case variations of asc and desc
|
||||
sort = QueryParsing.parseSort("score aSc", req);
|
||||
SortField[] flds = sort.getSort();
|
||||
assertEquals(flds[0].getType(), SortField.Type.SCORE);
|
||||
assertTrue(flds[0].getReverse());
|
||||
|
||||
spec = QueryParsing.parseSortSpec("score aSc", req);
|
||||
flds = spec.getSort().getSort();
|
||||
assertEquals(1, flds.length);
|
||||
assertEquals(flds[0].getType(), SortField.Type.SCORE);
|
||||
assertTrue(flds[0].getReverse());
|
||||
assertEquals(1, spec.getSchemaFields().size());
|
||||
assertNull(spec.getSchemaFields().get(0));
|
||||
|
||||
sort = QueryParsing.parseSort("weight dEsC", req);
|
||||
flds = sort.getSort();
|
||||
assertEquals(flds[0].getType(), SortField.Type.FLOAT);
|
||||
assertEquals(flds[0].getField(), "weight");
|
||||
assertEquals(flds[0].getReverse(), true);
|
||||
|
||||
spec = QueryParsing.parseSortSpec("weight dEsC", req);
|
||||
flds = spec.getSort().getSort();
|
||||
assertEquals(1, flds.length);
|
||||
assertEquals(flds[0].getType(), SortField.Type.FLOAT);
|
||||
assertEquals(flds[0].getField(), "weight");
|
||||
assertEquals(flds[0].getReverse(), true);
|
||||
assertEquals(1, spec.getSchemaFields().size());
|
||||
assertNotNull(spec.getSchemaFields().get(0));
|
||||
assertEquals("weight", spec.getSchemaFields().get(0).getName());
|
||||
|
||||
sort = QueryParsing.parseSort("weight desc,bday ASC", req);
|
||||
flds = sort.getSort();
|
||||
assertEquals(flds[0].getType(), SortField.Type.FLOAT);
|
||||
|
@ -149,18 +179,27 @@ public class QueryParsingTest extends SolrTestCaseJ4 {
|
|||
assertEquals(flds[0].getField(), "pow(float(weight),const(2.0))");
|
||||
|
||||
|
||||
sort = QueryParsing.parseSort("pow(weight, 2.0) desc, weight desc, bday asc", req);
|
||||
flds = sort.getSort();
|
||||
assertEquals(flds[0].getType(), SortField.Type.REWRITEABLE);
|
||||
spec = QueryParsing.parseSortSpec("pow(weight, 2.0) desc, weight desc, bday asc", req);
|
||||
flds = spec.getSort().getSort();
|
||||
List<SchemaField> schemaFlds = spec.getSchemaFields();
|
||||
assertEquals(3, flds.length);
|
||||
assertEquals(3, schemaFlds.size());
|
||||
|
||||
assertEquals(flds[0].getType(), SortField.Type.REWRITEABLE);
|
||||
//Not thrilled about the fragility of string matching here, but...
|
||||
//the value sources get wrapped, so the out field is different than the input
|
||||
assertEquals(flds[0].getField(), "pow(float(weight),const(2.0))");
|
||||
assertNull(schemaFlds.get(0));
|
||||
|
||||
assertEquals(flds[1].getType(), SortField.Type.FLOAT);
|
||||
assertEquals(flds[1].getField(), "weight");
|
||||
assertNotNull(schemaFlds.get(1));
|
||||
assertEquals("weight", schemaFlds.get(1).getName());
|
||||
|
||||
assertEquals(flds[2].getField(), "bday");
|
||||
assertEquals(flds[2].getType(), SortField.Type.LONG);
|
||||
assertNotNull(schemaFlds.get(2));
|
||||
assertEquals("bday", schemaFlds.get(2).getName());
|
||||
|
||||
//handles trailing commas
|
||||
sort = QueryParsing.parseSort("weight desc,", req);
|
||||
|
@ -178,6 +217,10 @@ public class QueryParsingTest extends SolrTestCaseJ4 {
|
|||
sort = QueryParsing.parseSort("", req);
|
||||
assertNull(sort);
|
||||
|
||||
spec = QueryParsing.parseSortSpec("", req);
|
||||
assertNotNull(spec);
|
||||
assertNull(spec.getSort());
|
||||
|
||||
req.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.lucene.util.Bits;
|
|||
import org.apache.lucene.util.OpenBitSet;
|
||||
import org.apache.lucene.util._TestUtil;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
|
@ -114,13 +115,18 @@ public class TestSort extends SolrTestCaseJ4 {
|
|||
}
|
||||
input.deleteCharAt(input.length()-1);
|
||||
SortField[] sorts = null;
|
||||
List<SchemaField> fields = null;
|
||||
try {
|
||||
sorts = QueryParsing.parseSort(input.toString(), req).getSort();
|
||||
SortSpec spec = QueryParsing.parseSortSpec(input.toString(), req);
|
||||
sorts = spec.getSort().getSort();
|
||||
fields = spec.getSchemaFields();
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException("Failed to parse sort: " + input, e);
|
||||
}
|
||||
assertEquals("parsed sorts had unexpected size",
|
||||
names.length, sorts.length);
|
||||
assertEquals("parsed sort schema fields had unexpected size",
|
||||
names.length, fields.size());
|
||||
for (int j = 0; j < names.length; j++) {
|
||||
assertEquals("sorts["+j+"] had unexpected reverse: " + input,
|
||||
reverse[j], sorts[j].getReverse());
|
||||
|
@ -144,6 +150,9 @@ public class TestSort extends SolrTestCaseJ4 {
|
|||
assertEquals("sorts["+j+"] ("+type.toString()+
|
||||
") had unexpected field in: " + input,
|
||||
names[j], sorts[j].getField());
|
||||
assertEquals("fields["+j+"] ("+type.toString()+
|
||||
") had unexpected name in: " + input,
|
||||
names[j], fields.get(j).getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue