Example usage for org.apache.lucene.search Sort getSort

List of usage examples for org.apache.lucene.search Sort getSort

Introduction

In this page you can find the example usage for org.apache.lucene.search Sort getSort.

Prototype

public SortField[] getSort() 

Source Link

Document

Representation of the sort criteria.

Usage

From source file:org.apache.solr.search.CursorMark.java

License:Apache License

/**
 * Generates an empty CursorMark bound for use with the 
 * specified schema and {@link SortSpec}.
 *
 * @param schema used for basic validation
 * @param sortSpec bound to this totem (un)marshalling serialized values
 *//*w  w  w .  j a  va2  s.co  m*/
public CursorMark(IndexSchema schema, SortSpec sortSpec) {

    final SchemaField uniqueKey = schema.getUniqueKeyField();
    if (null == uniqueKey) {
        throw new SolrException(ErrorCode.BAD_REQUEST,
                "Cursor functionality is not available unless the IndexSchema defines a uniqueKey field");
    }

    final Sort sort = sortSpec.getSort();
    if (null == sort) {
        // pure score, by definition we don't include the mandatyr uniqueKey tie breaker
        throw new SolrException(ErrorCode.BAD_REQUEST,
                "Cursor functionality requires a sort containing a uniqueKey field tie breaker");
    }

    if (!sortSpec.getSchemaFields().contains(uniqueKey)) {
        throw new SolrException(ErrorCode.BAD_REQUEST,
                "Cursor functionality requires a sort containing a uniqueKey field tie breaker");
    }

    if (0 != sortSpec.getOffset()) {
        throw new SolrException(ErrorCode.BAD_REQUEST, "Cursor functionality requires start=0");
    }

    for (SortField sf : sort.getSort()) {
        if (sf.getType().equals(SortField.Type.DOC)) {
            throw new SolrException(ErrorCode.BAD_REQUEST,
                    "Cursor functionality can not be used with internal doc ordering sort: _docid_");
        }
    }

    if (sort.getSort().length != sortSpec.getSchemaFields().size()) {
        throw new SolrException(ErrorCode.SERVER_ERROR, "Cursor SortSpec failure: sort length != SchemaFields: "
                + sort.getSort().length + " != " + sortSpec.getSchemaFields().size());
    }

    this.sortSpec = sortSpec;
    this.values = null;
}

From source file:org.apache.solr.search.EarlyTerminatingSortingCollector.java

License:Apache License

/** Returns whether collection can be early-terminated if it sorts with the
 *  provided {@link Sort} and if segments are merged with the provided
 *  {@link Sort}. *//*  ww w. j  a  v a 2  s .  co m*/
public static boolean canEarlyTerminate(Sort searchSort, Sort mergePolicySort) {
    final SortField[] fields1 = searchSort.getSort();
    final SortField[] fields2 = mergePolicySort.getSort();
    // early termination is possible if fields1 is a prefix of fields2
    if (fields1.length > fields2.length) {
        return false;
    }
    return Arrays.asList(fields1).equals(Arrays.asList(fields2).subList(0, fields1.length));
}

From source file:org.apache.solr.search.federated.DJoinMergeStrategy.java

License:Apache License

@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public void merge(ResponseBuilder rb, ShardRequest sreq) {
    SortSpec ss = rb.getSortSpec();/*from  w  w  w .j  a v  a  2 s . c o  m*/
    Sort sort = ss.getSort();

    SortField[] sortFields = null;
    if (sort != null)
        sortFields = sort.getSort();
    else {
        sortFields = new SortField[] { SortField.FIELD_SCORE };
    }

    IndexSchema schema = rb.req.getSchema();
    SchemaField uniqueKeyField = schema.getUniqueKeyField();

    // Merge the docs via a priority queue so we don't have to sort *all* of the
    // documents... we only need to order the top (rows+start)
    Map<String, NamedList> sortFieldValuesMap = new HashMap<>();
    Map<String, NamedList> unmarshalledSortFieldValuesMap = new HashMap<>();
    ShardFieldSortedHitQueue queue = new ShardFieldSortedHitQueue(unmarshalledSortFieldValuesMap, sortFields,
            ss.getOffset() + ss.getCount(), rb.req.getSearcher());

    NamedList<Object> shardInfo = null;
    if (rb.req.getParams().getBool(ShardParams.SHARDS_INFO, false)) {
        shardInfo = new SimpleOrderedMap<>();
        rb.rsp.getValues().add(ShardParams.SHARDS_INFO, shardInfo);
    }

    long numFound = 0;
    Float maxScore = null;
    boolean partialResults = false;
    for (ShardResponse srsp : sreq.responses) {
        String shard = srsp.getShard();
        // this hack is needed for test code since ShardResponse is so unfriendly
        if (shard == null) {
            shard = (String) srsp.getSolrResponse().getResponse().get("shard");
        }

        SolrDocumentList docs = null;

        if (shardInfo != null) {
            SimpleOrderedMap<Object> nl = new SimpleOrderedMap<>();

            if (srsp.getException() != null) {
                Throwable t = srsp.getException();
                if (t instanceof SolrServerException) {
                    t = ((SolrServerException) t).getCause();
                }
                nl.add("error", t.toString());
                StringWriter trace = new StringWriter();
                t.printStackTrace(new PrintWriter(trace));
                nl.add("trace", trace.toString());
                if (srsp.getShardAddress() != null) {
                    nl.add("shardAddress", srsp.getShardAddress());
                }
            } else {
                docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
                nl.add("numFound", docs.getNumFound());
                nl.add("maxScore", docs.getMaxScore());
                nl.add("shardAddress", srsp.getShardAddress());
            }
            if (srsp.getSolrResponse() != null) {
                nl.add("time", srsp.getSolrResponse().getElapsedTime());
            }

            shardInfo.add(shard, nl);
        }
        // now that we've added the shard info, let's only proceed if we have no error.
        if (srsp.getException() != null) {
            partialResults = true;
            continue;
        }

        if (docs == null) { // could have been initialized in the shards info block above
            docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
        }

        NamedList<?> responseHeader = (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader");
        if (responseHeader != null && Boolean.TRUE.equals(responseHeader.get("partialResults"))) {
            partialResults = true;
        }

        // calculate global maxScore and numDocsFound
        if (docs.getMaxScore() != null) {
            maxScore = maxScore == null ? docs.getMaxScore() : Math.max(maxScore, docs.getMaxScore());
        }
        numFound += docs.getNumFound();

        NamedList sortFieldValues = (NamedList) (srsp.getSolrResponse().getResponse().get("sort_values"));
        sortFieldValuesMap.put(shard, sortFieldValues);
        NamedList unmarshalledSortFieldValues = unmarshalSortValues(ss, sortFieldValues, schema);
        unmarshalledSortFieldValuesMap.put(shard, unmarshalledSortFieldValues);

        // go through every doc in this response, construct a ShardDoc, and
        // put it in the priority queue so it can be ordered.
        for (int i = 0; i < docs.size(); i++) {
            SolrDocument doc = docs.get(i);
            Object id = doc.getFieldValue(uniqueKeyField.getName());

            Object scoreObj = doc.getFieldValue("score");
            Float score = null;
            if (scoreObj != null) {
                if (scoreObj instanceof String) {
                    score = Float.parseFloat((String) scoreObj);
                } else {
                    score = (Float) scoreObj;
                }
            }

            ShardDoc shardDoc = new ShardDoc();
            shardDoc.id = id;
            shardDoc.shard = shard;
            shardDoc.orderInShard = i;
            if (score != null) {
                shardDoc.score = score;
            }

            queue.insertWithReplacement(shardDoc);
        } // end for-each-doc-in-response
    } // end for-each-response

    // The queue now has 0 -> queuesize docs, where queuesize <= start + rows
    // So we want to pop the last documents off the queue to get
    // the docs offset -> queuesize
    int resultSize = queue.size() - ss.getOffset();
    resultSize = Math.max(0, resultSize); // there may not be any docs in range

    // build resultIds, which is used to request fields from each shard, and initialise responseDocs
    DuplicateDocumentList responseDocs = new DuplicateDocumentList(resultSize, maxScore, numFound,
            ss.getOffset());
    Map<Object, ShardDoc> resultIds = new AllShardsResultIds(sreq.actualShards);
    for (int i = resultSize - 1; i >= 0; i--) {
        ShardDoc shardDoc = queue.pop();
        shardDoc.positionInResponse = i;

        // Need the toString() for correlation with other lists that must
        // be strings (like keys in highlighting, explain, etc)
        resultIds.put(shardDoc.id.toString(), shardDoc);

        // pre-populate responseDocs
        NamedList docSortValues = sortFieldValuesMap.get(shardDoc.shard);
        NamedList sortValue = new NamedList();
        for (int j = 0; j < docSortValues.size(); ++j) {
            String fieldName = docSortValues.getName(j);
            List values = (List) docSortValues.getVal(j);
            sortValue.add(fieldName, values.get(shardDoc.orderInShard));
        }
        responseDocs.setParentDoc(shardDoc.positionInResponse, docSortValues.size() > 0 ? sortValue : null,
                shardDoc.score);
    }

    // Add hits for distributed requests
    // https://issues.apache.org/jira/browse/SOLR-3518
    rb.rsp.addToLog("hits", numFound);

    // save these results in a private area so we can access them
    // again when retrieving stored fields.
    // TODO: use ResponseBuilder (w/ comments) or the request context?
    rb.resultIds = resultIds;
    rb.setResponseDocs(responseDocs);

    populateNextCursorMarkFromMergedShards(rb, unmarshalledSortFieldValuesMap);

    if (partialResults) {
        if (rb.rsp.getResponseHeader().get("partialResults") == null) {
            rb.rsp.getResponseHeader().add("partialResults", Boolean.TRUE);
        }
    }
}

From source file:org.apache.solr.search.grouping.distributed.shardresultserializer.SearchGroupsResultTransformer.java

License:Apache License

private NamedList serializeSearchGroup(Collection<SearchGroup<BytesRef>> data, Sort groupSort) {
    NamedList<Comparable[]> result = new NamedList<Comparable[]>();
    CharsRef spare = new CharsRef();

    for (SearchGroup<BytesRef> searchGroup : data) {
        Comparable[] convertedSortValues = new Comparable[searchGroup.sortValues.length];
        for (int i = 0; i < searchGroup.sortValues.length; i++) {
            Comparable sortValue = (Comparable) searchGroup.sortValues[i];
            SchemaField field = groupSort.getSort()[i].getField() != null
                    ? searcher.getSchema().getFieldOrNull(groupSort.getSort()[i].getField())
                    : null;//from   w w  w  .  java2s.c  o  m
            if (field != null) {
                FieldType fieldType = field.getType();
                if (sortValue instanceof BytesRef) {
                    UnicodeUtil.UTF8toUTF16((BytesRef) sortValue, spare);
                    String indexedValue = spare.toString();
                    sortValue = (Comparable) fieldType
                            .toObject(field.createField(fieldType.indexedToReadable(indexedValue), 1.0f));
                } else if (sortValue instanceof String) {
                    sortValue = (Comparable) fieldType
                            .toObject(field.createField(fieldType.indexedToReadable((String) sortValue), 1.0f));
                }
            }
            convertedSortValues[i] = sortValue;
        }
        String groupValue = searchGroup.groupValue != null ? searchGroup.groupValue.utf8ToString() : null;
        result.add(groupValue, convertedSortValues);
    }

    return result;
}

From source file:org.apache.solr.search.grouping.distributed.shardresultserializer.TopGroupsResultTransformer.java

License:Apache License

/**
 * {@inheritDoc}/*from  w w  w  .  j a v a 2s. com*/
 */
@Override
public Map<String, ?> transformToNative(NamedList<NamedList> shardResponse, Sort groupSort,
        Sort sortWithinGroup, String shard) {
    Map<String, Object> result = new HashMap<String, Object>();

    for (Map.Entry<String, NamedList> entry : shardResponse) {
        String key = entry.getKey();
        NamedList commandResult = entry.getValue();
        Integer totalGroupedHitCount = (Integer) commandResult.get("totalGroupedHitCount");
        Integer totalHits = (Integer) commandResult.get("totalHits");
        if (totalHits != null) {
            Integer matches = (Integer) commandResult.get("matches");
            Float maxScore = (Float) commandResult.get("maxScore");
            if (maxScore == null) {
                maxScore = Float.NaN;
            }

            @SuppressWarnings("unchecked")
            List<NamedList<Object>> documents = (List<NamedList<Object>>) commandResult.get("documents");
            ScoreDoc[] scoreDocs = new ScoreDoc[documents.size()];
            int j = 0;
            for (NamedList<Object> document : documents) {
                Object docId = document.get("id");
                Object uniqueId = null;
                if (docId != null)
                    uniqueId = docId.toString();
                else
                    log.warn("doc {} has null 'id'", document);
                Float score = (Float) document.get("score");
                if (score == null) {
                    score = Float.NaN;
                }
                Object[] sortValues = null;
                Object sortValuesVal = document.get("sortValues");
                if (sortValuesVal != null) {
                    sortValues = ((List) sortValuesVal).toArray();
                } else {
                    log.warn("doc {} has null 'sortValues'", document);
                }
                scoreDocs[j++] = new ShardDoc(score, sortValues, uniqueId, shard);
            }
            result.put(key, new QueryCommandResult(new TopDocs(totalHits, scoreDocs, maxScore), matches));
            continue;
        }

        Integer totalHitCount = (Integer) commandResult.get("totalHitCount");

        List<GroupDocs<BytesRef>> groupDocs = new ArrayList<GroupDocs<BytesRef>>();
        for (int i = 2; i < commandResult.size(); i++) {
            String groupValue = commandResult.getName(i);
            @SuppressWarnings("unchecked")
            NamedList<Object> groupResult = (NamedList<Object>) commandResult.getVal(i);
            Integer totalGroupHits = (Integer) groupResult.get("totalHits");
            Float maxScore = (Float) groupResult.get("maxScore");
            if (maxScore == null) {
                maxScore = Float.NaN;
            }

            @SuppressWarnings("unchecked")
            List<NamedList<Object>> documents = (List<NamedList<Object>>) groupResult.get("documents");
            ScoreDoc[] scoreDocs = new ScoreDoc[documents.size()];
            int j = 0;
            for (NamedList<Object> document : documents) {
                Object uniqueId = document.get("id").toString();
                Float score = (Float) document.get("score");
                if (score == null) {
                    score = Float.NaN;
                }
                Object[] sortValues = ((List) document.get("sortValues")).toArray();
                scoreDocs[j++] = new ShardDoc(score, sortValues, uniqueId, shard);
            }

            BytesRef groupValueRef = groupValue != null ? new BytesRef(groupValue) : null;
            groupDocs.add(new GroupDocs<BytesRef>(Float.NaN, maxScore, totalGroupHits, scoreDocs, groupValueRef,
                    null));
        }

        @SuppressWarnings("unchecked")
        GroupDocs<BytesRef>[] groupDocsArr = groupDocs.toArray(new GroupDocs[groupDocs.size()]);
        TopGroups<BytesRef> topGroups = new TopGroups<BytesRef>(groupSort.getSort(), sortWithinGroup.getSort(),
                totalHitCount, totalGroupedHitCount, groupDocsArr, Float.NaN);

        result.put(key, topGroups);
    }

    return result;
}

From source file:org.apache.solr.search.grouping.distributed.shardresultserializer.TopGroupsResultTransformer.java

License:Apache License

protected NamedList serializeTopGroups(TopGroups<BytesRef> data, SchemaField groupField) throws IOException {
    NamedList<Object> result = new NamedList<Object>();
    result.add("totalGroupedHitCount", data.totalGroupedHitCount);
    result.add("totalHitCount", data.totalHitCount);
    if (data.totalGroupCount != null) {
        result.add("totalGroupCount", data.totalGroupCount);
    }//from   www  .  j  a  va 2s  .  c  om
    CharsRef spare = new CharsRef();

    final IndexSchema schema = rb.req.getSearcher().getSchema();
    SchemaField uniqueField = schema.getUniqueKeyField();
    for (GroupDocs<BytesRef> searchGroup : data.groups) {
        NamedList<Object> groupResult = new NamedList<Object>();
        groupResult.add("totalHits", searchGroup.totalHits);
        if (!Float.isNaN(searchGroup.maxScore)) {
            groupResult.add("maxScore", searchGroup.maxScore);
        }

        List<NamedList<Object>> documents = new ArrayList<NamedList<Object>>();
        for (int i = 0; i < searchGroup.scoreDocs.length; i++) {
            NamedList<Object> document = new NamedList<Object>();
            documents.add(document);

            Document doc = retrieveDocument(uniqueField, searchGroup.scoreDocs[i].doc);
            document.add("id", uniqueField.getType().toExternal(doc.getField(uniqueField.getName())));
            if (!Float.isNaN(searchGroup.scoreDocs[i].score)) {
                document.add("score", searchGroup.scoreDocs[i].score);
            }
            if (!(searchGroup.scoreDocs[i] instanceof FieldDoc)) {
                continue;
            }

            FieldDoc fieldDoc = (FieldDoc) searchGroup.scoreDocs[i];
            Object[] convertedSortValues = new Object[fieldDoc.fields.length];
            for (int j = 0; j < fieldDoc.fields.length; j++) {
                Object sortValue = fieldDoc.fields[j];
                Sort sortWithinGroup = rb.getGroupingSpec().getSortWithinGroup();
                SchemaField field = sortWithinGroup.getSort()[j].getField() != null
                        ? schema.getFieldOrNull(sortWithinGroup.getSort()[j].getField())
                        : null;
                if (field != null) {
                    FieldType fieldType = field.getType();
                    if (sortValue instanceof BytesRef) {
                        UnicodeUtil.UTF8toUTF16((BytesRef) sortValue, spare);
                        String indexedValue = spare.toString();
                        sortValue = fieldType
                                .toObject(field.createField(fieldType.indexedToReadable(indexedValue), 1.0f));
                    } else if (sortValue instanceof String) {
                        sortValue = fieldType.toObject(
                                field.createField(fieldType.indexedToReadable((String) sortValue), 1.0f));
                    }
                }
                convertedSortValues[j] = sortValue;
            }
            document.add("sortValues", convertedSortValues);
        }
        groupResult.add("documents", documents);
        String groupValue = searchGroup.groupValue != null
                ? groupField.getType().indexedToReadable(searchGroup.groupValue.utf8ToString())
                : null;
        result.add(groupValue, groupResult);
    }

    return result;
}

From source file:org.apache.solr.search.grouping.distributed.shardresultserializer.TopGroupsResultTransformer.java

License:Apache License

protected NamedList serializeTopDocs(QueryCommandResult result) throws IOException {
    NamedList<Object> queryResult = new NamedList<Object>();
    queryResult.add("matches", result.getMatches());
    queryResult.add("totalHits", result.getTopDocs().totalHits);
    if (rb.getGroupingSpec().isNeedScore()) {
        queryResult.add("maxScore", result.getTopDocs().getMaxScore());
    }/*from  ww  w.  j  a  va 2  s.  c o  m*/
    List<NamedList> documents = new ArrayList<NamedList>();
    queryResult.add("documents", documents);

    final IndexSchema schema = rb.req.getSearcher().getSchema();
    SchemaField uniqueField = schema.getUniqueKeyField();
    CharsRef spare = new CharsRef();
    for (ScoreDoc scoreDoc : result.getTopDocs().scoreDocs) {
        NamedList<Object> document = new NamedList<Object>();
        documents.add(document);

        Document doc = retrieveDocument(uniqueField, scoreDoc.doc);
        document.add("id", uniqueField.getType().toExternal(doc.getField(uniqueField.getName())));
        if (rb.getGroupingSpec().isNeedScore()) {
            document.add("score", scoreDoc.score);
        }
        if (!FieldDoc.class.isInstance(scoreDoc)) {
            continue;
        }

        FieldDoc fieldDoc = (FieldDoc) scoreDoc;
        Object[] convertedSortValues = new Object[fieldDoc.fields.length];
        for (int j = 0; j < fieldDoc.fields.length; j++) {
            Object sortValue = fieldDoc.fields[j];
            Sort groupSort = rb.getGroupingSpec().getGroupSort();
            SchemaField field = groupSort.getSort()[j].getField() != null
                    ? schema.getFieldOrNull(groupSort.getSort()[j].getField())
                    : null;
            if (field != null) {
                FieldType fieldType = field.getType();
                if (sortValue instanceof BytesRef) {
                    UnicodeUtil.UTF8toUTF16((BytesRef) sortValue, spare);
                    String indexedValue = spare.toString();
                    sortValue = fieldType
                            .toObject(field.createField(fieldType.indexedToReadable(indexedValue), 1.0f));
                } else if (sortValue instanceof String) {
                    sortValue = fieldType
                            .toObject(field.createField(fieldType.indexedToReadable((String) sortValue), 1.0f));
                }
            }
            convertedSortValues[j] = sortValue;
        }
        document.add("sortValues", convertedSortValues);
    }

    return queryResult;
}

From source file:org.apache.solr.search.join.TestNestedDocsSort.java

License:Apache License

private SortField parse(String a) {
    final SolrQueryRequest req = req("q", "{!parent which=type_s1:parent}whatever_s1:foo", "q2",
            "{!parent which=type_s1:parent}nomater_s1:what", "notbjq", "foo_s1:bar");
    try {/*from  w w  w . j  a  v  a  2  s  .  c  om*/
        final SortSpec spec = SortSpecParsing.parseSortSpec(a, req);
        assertNull(spec.getSchemaFields().get(0));
        final Sort sort = spec.getSort();
        final SortField field = sort.getSort()[0];
        assertNotNull(field);
        return field;
    } finally {
        req.close();
    }
}

From source file:org.apache.solr.search.MultiCollector.java

License:Apache License

public TopGroupCollector(ValueSource groupByVS, Map vsContext, Sort sort, int nGroups) throws IOException {
    this.vs = groupByVS;
    this.context = vsContext;
    this.nGroups = nGroups;

    SortField[] sortFields = sort.getSort();
    this.comparators = new FieldComparator[sortFields.length];
    this.reversed = new int[sortFields.length];
    for (int i = 0; i < sortFields.length; i++) {
        SortField sortField = sortFields[i];
        reversed[i] = sortField.getReverse() ? -1 : 1;
        // use nGroups + 1 so we have a spare slot to use for comparing (tracked by this.spareSlot)
        comparators[i] = sortField.getComparator(nGroups + 1, i);
    }/*from   w  w  w.j  a  va 2s.  com*/
    this.spareSlot = nGroups;

    this.groupMap = new HashMap<MutableValue, SearchGroup>(nGroups);
}

From source file:org.apache.solr.search.QueryParsingTest.java

License:Apache License

@Test
public void testSort() throws Exception {
    Sort sort;
    SolrQueryRequest req = req();//from w  w w .j  a  va  2  s .  c om

    sort = QueryParsing.parseSort("score desc", req);
    assertNull("sort", sort);//only 1 thing in the list, no Sort specified

    // 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());

    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);
    sort = QueryParsing.parseSort("weight desc,bday ASC", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.FLOAT);
    assertEquals(flds[0].getField(), "weight");
    assertEquals(flds[0].getReverse(), true);
    assertEquals(flds[1].getType(), SortField.Type.LONG);
    assertEquals(flds[1].getField(), "bday");
    assertEquals(flds[1].getReverse(), false);
    //order aliases
    sort = QueryParsing.parseSort("weight top,bday asc", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.FLOAT);
    assertEquals(flds[0].getField(), "weight");
    assertEquals(flds[0].getReverse(), true);
    assertEquals(flds[1].getType(), SortField.Type.LONG);
    assertEquals(flds[1].getField(), "bday");
    assertEquals(flds[1].getReverse(), false);
    sort = QueryParsing.parseSort("weight top,bday bottom", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.FLOAT);
    assertEquals(flds[0].getField(), "weight");
    assertEquals(flds[0].getReverse(), true);
    assertEquals(flds[1].getType(), SortField.Type.LONG);
    assertEquals(flds[1].getField(), "bday");
    assertEquals(flds[1].getReverse(), false);

    //test weird spacing
    sort = QueryParsing.parseSort("weight         DESC,            bday         asc", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.FLOAT);
    assertEquals(flds[0].getField(), "weight");
    assertEquals(flds[1].getField(), "bday");
    assertEquals(flds[1].getType(), SortField.Type.LONG);
    //handles trailing commas
    sort = QueryParsing.parseSort("weight desc,", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.FLOAT);
    assertEquals(flds[0].getField(), "weight");

    //test functions
    sort = QueryParsing.parseSort("pow(weight, 2) desc", req);
    flds = sort.getSort();
    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))");

    //test functions (more deep)
    sort = QueryParsing.parseSort("sum(product(r_f1,sum(d_f1,t_f1,1.0)),a_f1) asc", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.REWRITEABLE);
    assertEquals(flds[0].getField(),
            "sum(product(float(r_f1),sum(float(d_f1),float(t_f1),const(1.0))),float(a_f1))");

    sort = QueryParsing.parseSort("pow(weight,                 2.0)         desc", req);
    flds = sort.getSort();
    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))");

    sort = QueryParsing.parseSort("pow(weight, 2.0) desc, weight    desc,   bday    asc", req);
    flds = sort.getSort();
    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))");

    assertEquals(flds[1].getType(), SortField.Type.FLOAT);
    assertEquals(flds[1].getField(), "weight");
    assertEquals(flds[2].getField(), "bday");
    assertEquals(flds[2].getType(), SortField.Type.LONG);

    //handles trailing commas
    sort = QueryParsing.parseSort("weight desc,", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.FLOAT);
    assertEquals(flds[0].getField(), "weight");

    //Test literals in functions
    sort = QueryParsing.parseSort("strdist(foo_s1, \"junk\", jw) desc", req);
    flds = sort.getSort();
    assertEquals(flds[0].getType(), SortField.Type.REWRITEABLE);
    //the value sources get wrapped, so the out field is different than the input
    assertEquals(flds[0].getField(),
            "strdist(str(foo_s1),literal(junk), dist=org.apache.lucene.search.spell.JaroWinklerDistance)");

    sort = QueryParsing.parseSort("", req);
    assertNull(sort);

    req.close();
}