/* * 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.search; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.SolrException; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.schema.SchemaField; import org.junit.BeforeClass; import org.junit.Test; import java.util.List; /** * * **/ public class SortSpecParsingTest extends SolrTestCaseJ4 { @BeforeClass public static void beforeClass() throws Exception { initCore("solrconfig.xml","schema.xml"); } private static SortSpec doParseSortSpec(String sortSpec, SolrQueryRequest req) { if (random().nextBoolean()) { return SortSpecParsing.parseSortSpec(sortSpec, req.getSchema()); } else { return SortSpecParsing.parseSortSpec(sortSpec, req); } } @Test public void testSort() throws Exception { Sort sort; SortSpec spec; SolrQueryRequest req = req(); sort = doParseSortSpec("score desc", req).getSort(); assertNull("sort", sort);//only 1 thing in the list, no Sort specified spec = doParseSortSpec("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 = doParseSortSpec("score aSc", req).getSort(); SortField[] flds = sort.getSort(); assertEquals(flds[0].getType(), SortField.Type.SCORE); assertTrue(flds[0].getReverse()); spec = doParseSortSpec("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 = doParseSortSpec("weight dEsC", req).getSort(); flds = sort.getSort(); assertEquals(flds[0].getType(), SortField.Type.FLOAT); assertEquals(flds[0].getField(), "weight"); assertEquals(flds[0].getReverse(), true); spec = doParseSortSpec("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 = doParseSortSpec("weight desc,bday ASC", req).getSort(); 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 = doParseSortSpec("weight top,bday asc", req).getSort(); 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 = doParseSortSpec("weight top,bday bottom", req).getSort(); 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 = doParseSortSpec("weight DESC, bday asc", req).getSort(); 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 = doParseSortSpec("weight desc,", req).getSort(); flds = sort.getSort(); assertEquals(flds[0].getType(), SortField.Type.FLOAT); assertEquals(flds[0].getField(), "weight"); //test functions sort = SortSpecParsing.parseSortSpec("pow(weight, 2) desc", req).getSort(); 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 = SortSpecParsing.parseSortSpec("sum(product(r_f1,sum(d_f1,t_f1,1.0)),a_f1) asc", req).getSort(); 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 = SortSpecParsing.parseSortSpec("pow(weight, 2.0) desc", req).getSort(); 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))"); spec = SortSpecParsing.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 = doParseSortSpec("weight desc,", req).getSort(); flds = sort.getSort(); assertEquals(flds[0].getType(), SortField.Type.FLOAT); assertEquals(flds[0].getField(), "weight"); //Test literals in functions sort = SortSpecParsing.parseSortSpec("strdist(foo_s1, \"junk\", jw) desc", req).getSort(); 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 = doParseSortSpec("", req).getSort(); assertNull(sort); spec = doParseSortSpec("", req); assertNotNull(spec); assertNull(spec.getSort()); req.close(); } @Test public void testBad() throws Exception { Sort sort; SolrQueryRequest req = req(); //test some bad vals try { sort = doParseSortSpec("weight, desc", req).getSort(); assertTrue(false); } catch (SolrException e) { //expected } try { sort = doParseSortSpec("w", req).getSort(); assertTrue(false); } catch (SolrException e) { //expected } try { sort = doParseSortSpec("weight desc, bday", req).getSort(); assertTrue(false); } catch (SolrException e) { } try { //bad number of commas sort = SortSpecParsing.parseSortSpec("pow(weight,,2) desc, bday asc", req).getSort(); assertTrue(false); } catch (SolrException e) { } try { //bad function sort = SortSpecParsing.parseSortSpec("pow() desc, bday asc", req).getSort(); assertTrue(false); } catch (SolrException e) { } try { //bad number of parens sort = SortSpecParsing.parseSortSpec("pow((weight,2) desc, bday asc", req).getSort(); assertTrue(false); } catch (SolrException e) { } req.close(); } }