SOLR-170 -- adding a 'sort' parameter that works for both dismax and standard request handlers. The ';' is still suported (if the 'sort' parameter is not in the query). This also adds a new test class for StandardRequestHandler.

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@533566 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan McKinley 2007-04-29 22:10:20 +00:00
parent d273f54151
commit aa93003946
8 changed files with 144 additions and 28 deletions

View File

@ -158,6 +158,10 @@ New Features
<requestDispatcher handleSelect="true" > to your solrconfig.xml
See the example solrconfig.xml for details. (ryan)
26. SOLR-170: StandardRequestHandler now supports a "sort" parameter.
Using the ';' syntax is still supported, but it is recommended to
transition to the new syntax. (ryan)
Changes in runtime behavior
1. Highlighting using DisMax will only pick up terms from the main
user query, not boost or filter queries (klaas).

View File

@ -37,6 +37,8 @@ public abstract class SolrParams {
public static final String WT ="wt";
/** query string */
public static final String Q ="q";
/** sort order */
public static final String SORT ="sort";
/** Lucene query string(s) for filtering the results without affecting scoring */
public static final String FQ ="fq";
/** zero based offset of matching documents to retrieve */
@ -364,3 +366,5 @@ public abstract class SolrParams {

View File

@ -67,7 +67,7 @@ public class StandardRequestHandler extends RequestHandlerBase {
{
SolrParams p = req.getParams();
String sreq = p.get(Q);
String qstr = p.required().get(Q);
String defaultField = p.get(DF);
@ -78,24 +78,36 @@ public class StandardRequestHandler extends RequestHandlerBase {
flags |= U.setReturnFields(fl, rsp);
}
if (sreq==null) throw new SolrException(400,"Missing queryString");
List<String> commands = StrUtils.splitSmart(sreq,';');
String sortStr = p.get(SORT);
if( sortStr == null ) {
// TODO? should we disable the ';' syntax with config?
// legacy mode, where sreq is query;sort
List<String> commands = StrUtils.splitSmart(qstr,';');
if( commands.size() == 2 ) {
// TODO? add a deprication warning to the response header
qstr = commands.get( 0 );
sortStr = commands.get( 1 );
}
else if( commands.size() == 1 ) {
// This is need to support the case where someone sends: "q=query;"
qstr = commands.get( 0 );
}
else if( commands.size() > 2 ) {
throw new SolrException( 400, "If you want to use multiple ';' in the query, use the 'sort' param." );
}
}
String qs = commands.size() >= 1 ? commands.get(0) : "";
Query query = QueryParsing.parseQuery(qs, defaultField, p, req.getSchema());
// If the first non-query, non-filter command is a simple sort on an indexed field, then
// we can use the Lucene sort ability.
Sort sort = null;
if (commands.size() >= 2) {
QueryParsing.SortSpec sortSpec = QueryParsing.parseSort(commands.get(1), req.getSchema());
if( sortStr != null ) {
QueryParsing.SortSpec sortSpec = QueryParsing.parseSort(sortStr, req.getSchema());
if (sortSpec != null) {
sort = sortSpec.getSort();
// ignore the count for now... it's currently only controlled by start & limit on req
// count = sortSpec.getCount();
}
}
// parse the query from the 'q' parameter (sort has been striped)
Query query = QueryParsing.parseQuery(qstr, defaultField, p, req.getSchema());
DocListAndSet results = new DocListAndSet();
NamedList facetInfo = null;
List<Query> filters = U.parseFilterQueries(req);
@ -120,7 +132,7 @@ public class StandardRequestHandler extends RequestHandlerBase {
if (null != facetInfo) rsp.add("facet_counts", facetInfo);
try {
NamedList dbg = U.doStandardDebug(req, qs, query, results.docList);
NamedList dbg = U.doStandardDebug(req, qstr, query, results.docList);
if (null != dbg) {
if (null != filters) {
dbg.add("filter_queries",req.getParams().getParams(FQ));
@ -188,3 +200,5 @@ public class StandardRequestHandler extends RequestHandlerBase {
}
}

View File

@ -785,7 +785,7 @@ public class SolrPluginUtils {
*/
public static Sort getSort(SolrQueryRequest req) {
String sort = req.getParam("sort");
String sort = req.getParam(SolrParams.SORT);
if (null == sort || sort.equals("")) {
return null;
}
@ -866,3 +866,5 @@ public class SolrPluginUtils {

View File

@ -261,7 +261,7 @@ curl http://localhost:8983/solr/update --data-binary '&lt;commit/>'
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;fl=name,id">q=video&amp;fl=name,id</a> (return only name and id fields) </li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;fl=name,id,score">q=video&amp;fl=name,id,score</a> (return relevancy score as well) </li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;fl=*,score">q=video&amp;fl=*,score</a> (return all stored fields, as well as relevancy score) </li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video;price desc&amp;fl=name,id">q=video;price desc&amp;fl=name,id</a> (add sort specification: sort by price descending) </li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video;price desc&amp;fl=name,id">q=video&amp;sort=price desc&amp;fl=name,id</a> (add sort specification: sort by price descending) </li>
</ul>
<p>
@ -273,21 +273,21 @@ curl http://localhost:8983/solr/update --data-binary '&lt;commit/>'
<title>Sorting</title>
<p>
Solr provides a simple extension to the Lucene QueryParser syntax for specifying sort options. After your search, add a semi-colon followed by a list of "field direction" pairs...
Solr provides a simple extension to the Lucene QueryParser syntax for specifying sort options. Use the 'sort' parameter to specify "field direction" pairs...
</p>
<ul>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video;price+desc">video; price desc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video;price+asc">video; price asc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video;inStock+asc+price+desc">video; inStock asc, price desc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;sort=price+desc">video; price desc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;sort=price+asc">video; price asc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;sort=inStock+asc+price+desc">video; inStock asc, price desc</a></li>
</ul>
<p>
"score" can also be used as a field name when specifying a sort...
</p>
<ul>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video;score+desc">video; score desc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video;inStock+asc,score+desc">video; inStock asc, score desc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;sort=score+desc">video; score desc</a></li>
<li><a href="http://localhost:8983/solr/select/?indent=on&amp;q=video&amp;sort=inStock+asc,score+desc">video; inStock asc, score desc</a></li>
</ul>
<p>

View File

@ -583,7 +583,6 @@ public class BasicFunctionalityTest extends AbstractSolrTestCase {
,"facet.mincount","0"
,"facet.offset","0"
,"facet.limit","3"
,"sort","true"
)
,"*[count(//lst[@name='trait_s']/int)=3]"
,"//lst[@name='trait_s']/int[@name='Tool'][.='2']"

View File

@ -0,0 +1,93 @@
/**
* 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.handler;
import java.util.HashMap;
import java.util.Map;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.MapSolrParams;
import org.apache.solr.request.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.util.AbstractSolrTestCase;
/**
* Most of the tests for StandardRequestHandler are in ConvertedLegacyTest
*
*/
public class StandardRequestHandlerTest extends AbstractSolrTestCase {
@Override public String getSchemaFile() { return "schema.xml"; }
@Override public String getSolrConfigFile() { return "solrconfig.xml"; }
@Override public void setUp() throws Exception {
super.setUp();
lrf = h.getRequestFactory("standard", 0, 20 );
}
public void testSorting() throws Exception {
assertU(adoc("id", "10", "title", "test", "val_s", "aaa"));
assertU(adoc("id", "11", "title", "test", "val_s", "bbb"));
assertU(adoc("id", "12", "title", "test", "val_s", "ccc"));
assertU(commit());
Map<String,String> args = new HashMap<String, String>();
args.put( SolrParams.Q, "title:test" );
args.put( "indent", "true" );
SolrQueryRequest req = new LocalSolrQueryRequest( SolrCore.getSolrCore(), new MapSolrParams( args) );
assertQ("Make sure they got in", req
,"//*[@numFound='3']"
);
args.put( SolrParams.SORT, "val_s asc" );
assertQ("with sort param [asc]", req
,"//*[@numFound='3']"
,"//result/doc[1]/int[@name='id'][.='10']"
,"//result/doc[2]/int[@name='id'][.='11']"
,"//result/doc[3]/int[@name='id'][.='12']"
);
args.put( SolrParams.SORT, "val_s desc" );
assertQ("with sort param [desc]", req
,"//*[@numFound='3']"
,"//result/doc[1]/int[@name='id'][.='12']"
,"//result/doc[2]/int[@name='id'][.='11']"
,"//result/doc[3]/int[@name='id'][.='10']"
);
// Using legacy ';' param
args.remove( SolrParams.SORT );
args.put( SolrParams.Q, "title:test; val_s desc" );
assertQ("with sort param [desc]", req
,"//*[@numFound='3']"
,"//result/doc[1]/int[@name='id'][.='12']"
,"//result/doc[2]/int[@name='id'][.='11']"
,"//result/doc[3]/int[@name='id'][.='10']"
);
args.put( SolrParams.Q, "title:test; val_s asc" );
assertQ("with sort param [desc]", req
,"//*[@numFound='3']"
,"//result/doc[1]/int[@name='id'][.='10']"
,"//result/doc[2]/int[@name='id'][.='11']"
,"//result/doc[3]/int[@name='id'][.='12']"
);
}
}

View File

@ -298,7 +298,7 @@
<fields>
<field name="id" type="integer" indexed="true" stored="true"/>
<field name="id" type="integer" indexed="true" stored="true" multiValued="false"/>
<field name="name" type="nametext" indexed="true" stored="true"/>
<field name="text" type="text" indexed="true" stored="false"/>
<field name="subject" type="text" indexed="true" stored="true"/>