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

@ -157,6 +157,10 @@ New Features
/select. To enable this behavior, you must add: /select. To enable this behavior, you must add:
<requestDispatcher handleSelect="true" > to your solrconfig.xml <requestDispatcher handleSelect="true" > to your solrconfig.xml
See the example solrconfig.xml for details. (ryan) 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 Changes in runtime behavior
1. Highlighting using DisMax will only pick up terms from the main 1. Highlighting using DisMax will only pick up terms from the main

View File

@ -37,6 +37,8 @@ public abstract class SolrParams {
public static final String WT ="wt"; public static final String WT ="wt";
/** query string */ /** query string */
public static final String Q ="q"; 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 */ /** Lucene query string(s) for filtering the results without affecting scoring */
public static final String FQ ="fq"; public static final String FQ ="fq";
/** zero based offset of matching documents to retrieve */ /** 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(); SolrParams p = req.getParams();
String sreq = p.get(Q); String qstr = p.required().get(Q);
String defaultField = p.get(DF); String defaultField = p.get(DF);
@ -77,25 +77,37 @@ public class StandardRequestHandler extends RequestHandlerBase {
if (fl != null) { if (fl != null) {
flags |= U.setReturnFields(fl, rsp); flags |= U.setReturnFields(fl, rsp);
} }
if (sreq==null) throw new SolrException(400,"Missing queryString"); String sortStr = p.get(SORT);
List<String> commands = StrUtils.splitSmart(sreq,';'); if( sortStr == null ) {
// TODO? should we disable the ';' syntax with config?
String qs = commands.size() >= 1 ? commands.get(0) : ""; // legacy mode, where sreq is query;sort
Query query = QueryParsing.parseQuery(qs, defaultField, p, req.getSchema()); List<String> commands = StrUtils.splitSmart(qstr,';');
if( commands.size() == 2 ) {
// If the first non-query, non-filter command is a simple sort on an indexed field, then // TODO? add a deprication warning to the response header
// we can use the Lucene sort ability. qstr = commands.get( 0 );
Sort sort = null; sortStr = commands.get( 1 );
if (commands.size() >= 2) { }
QueryParsing.SortSpec sortSpec = QueryParsing.parseSort(commands.get(1), req.getSchema()); else if( commands.size() == 1 ) {
if (sortSpec != null) { // This is need to support the case where someone sends: "q=query;"
sort = sortSpec.getSort(); qstr = commands.get( 0 );
// ignore the count for now... it's currently only controlled by start & limit on req }
// count = sortSpec.getCount(); else if( commands.size() > 2 ) {
throw new SolrException( 400, "If you want to use multiple ';' in the query, use the 'sort' param." );
} }
} }
Sort sort = null;
if( sortStr != null ) {
QueryParsing.SortSpec sortSpec = QueryParsing.parseSort(sortStr, req.getSchema());
if (sortSpec != null) {
sort = sortSpec.getSort();
}
}
// parse the query from the 'q' parameter (sort has been striped)
Query query = QueryParsing.parseQuery(qstr, defaultField, p, req.getSchema());
DocListAndSet results = new DocListAndSet(); DocListAndSet results = new DocListAndSet();
NamedList facetInfo = null; NamedList facetInfo = null;
List<Query> filters = U.parseFilterQueries(req); List<Query> filters = U.parseFilterQueries(req);
@ -120,7 +132,7 @@ public class StandardRequestHandler extends RequestHandlerBase {
if (null != facetInfo) rsp.add("facet_counts", facetInfo); if (null != facetInfo) rsp.add("facet_counts", facetInfo);
try { try {
NamedList dbg = U.doStandardDebug(req, qs, query, results.docList); NamedList dbg = U.doStandardDebug(req, qstr, query, results.docList);
if (null != dbg) { if (null != dbg) {
if (null != filters) { if (null != filters) {
dbg.add("filter_queries",req.getParams().getParams(FQ)); 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) { public static Sort getSort(SolrQueryRequest req) {
String sort = req.getParam("sort"); String sort = req.getParam(SolrParams.SORT);
if (null == sort || sort.equals("")) { if (null == sort || sort.equals("")) {
return null; 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">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=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&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> </ul>
<p> <p>
@ -273,21 +273,21 @@ curl http://localhost:8983/solr/update --data-binary '&lt;commit/>'
<title>Sorting</title> <title>Sorting</title>
<p> <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> </p>
<ul> <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&amp;sort=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&amp;sort=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=inStock+asc+price+desc">video; inStock asc, price desc</a></li>
</ul> </ul>
<p> <p>
"score" can also be used as a field name when specifying a sort... "score" can also be used as a field name when specifying a sort...
</p> </p>
<ul> <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&amp;sort=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=inStock+asc,score+desc">video; inStock asc, score desc</a></li>
</ul> </ul>
<p> <p>

View File

@ -583,7 +583,6 @@ public class BasicFunctionalityTest extends AbstractSolrTestCase {
,"facet.mincount","0" ,"facet.mincount","0"
,"facet.offset","0" ,"facet.offset","0"
,"facet.limit","3" ,"facet.limit","3"
,"sort","true"
) )
,"*[count(//lst[@name='trait_s']/int)=3]" ,"*[count(//lst[@name='trait_s']/int)=3]"
,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" ,"//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> <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="name" type="nametext" indexed="true" stored="true"/>
<field name="text" type="text" indexed="true" stored="false"/> <field name="text" type="text" indexed="true" stored="false"/>
<field name="subject" type="text" indexed="true" stored="true"/> <field name="subject" type="text" indexed="true" stored="true"/>