/* * 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.component; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.spelling.suggest.SuggesterParams; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import static org.hamcrest.core.Is.is; public class SuggestComponentContextFilterQueryTest extends SolrTestCaseJ4 { static String rh = "/suggest"; @BeforeClass public static void beforeClass() throws Exception { initCore("solrconfig-suggestercomponent-context-filter-query.xml", "schema.xml"); } @Override public void setUp() throws Exception { super.setUp(); assertU(delQ("*:*")); // id, cat, price, weight, contexts assertU(adoc("id", "0", "cat", "This is a title", "price", "5", "weight", "10", "my_contexts_t", "ctx1")); assertU(adoc("id", "1", "cat", "This is another title", "price", "10", "weight", "10", "my_contexts_t", "ctx1")); assertU(adoc("id", "7", "cat", "example with ctx1 at 40", "price", "40", "weight", "30", "my_contexts_t", "ctx1")); assertU(adoc("id", "8", "cat", "example with ctx2 and ctx3 at 45", "price", "45", "weight", "30", "my_contexts_t", "CTX2", "my_contexts_t", "CTX3")); assertU(adoc("id", "9", "cat", "example with ctx4 at 50 using my_contexts_s", "price", "50", "weight", "40", "my_contexts_s", "ctx4")); assertU((commit())); waitForWarming(); } @Test public void testContextFilterParamIsIgnoredWhenContextIsNotImplemented() throws Exception { assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_lookup_has_no_context_implementation", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "ctx1", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_lookup_has_no_context_implementation']/lst[@name='examp']/int[@name='numFound'][.='3']", "//lst[@name='suggest']/lst[@name='suggest_lookup_has_no_context_implementation']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx4 at 50 using my_contexts_s']", "//lst[@name='suggest']/lst[@name='suggest_lookup_has_no_context_implementation']/lst[@name='examp']/arr[@name='suggestions']/lst[2]/str[@name='term'][.='example with ctx2 and ctx3 at 45']", "//lst[@name='suggest']/lst[@name='suggest_lookup_has_no_context_implementation']/lst[@name='examp']/arr[@name='suggestions']/lst[3]/str[@name='term'][.='example with ctx1 at 40']" ); } @Test public void testContextFilteringIsIgnoredWhenContextIsImplementedButNotConfigured() throws Exception { assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_context_implemented_but_not_configured", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_context_implemented_but_not_configured']/lst[@name='examp']/int[@name='numFound'][.='3']", "//lst[@name='suggest']/lst[@name='suggest_context_implemented_but_not_configured']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx4 at 50 using my_contexts_s']", "//lst[@name='suggest']/lst[@name='suggest_context_implemented_but_not_configured']/lst[@name='examp']/arr[@name='suggestions']/lst[2]/str[@name='term'][.='example with ctx2 and ctx3 at 45']", "//lst[@name='suggest']/lst[@name='suggest_context_implemented_but_not_configured']/lst[@name='examp']/arr[@name='suggestions']/lst[3]/str[@name='term'][.='example with ctx1 at 40']" ); } @Test public void testBuildThrowsIllegalArgumentExceptionWhenContextIsConfiguredButNotImplemented() throws Exception { try { assertQ( req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_context_filtering_not_implemented", SuggesterParams.SUGGEST_Q, "examp") , "" ); fail("Expecting exception because "); } catch (RuntimeException e) { Throwable cause = e.getCause(); assertTrue(cause instanceof IllegalArgumentException); assertThat(cause.getMessage(), is("this suggester doesn't support contexts")); } // When not building, no exception is thrown assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "false", SuggesterParams.SUGGEST_DICT, "suggest_context_filtering_not_implemented", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_context_filtering_not_implemented']/lst[@name='examp']/int[@name='numFound'][.='0']" ); } @Test public void testContextFilterIsTrimmed() throws Exception { assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, " ", //trimmed to null... just as if there was no context filter param SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='3']" ); } public void testExplicitFieldedQuery() throws Exception { assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "contexts:ctx1", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='1']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx1 at 40']" ); } public void testContextFilterOK() throws Exception { //No filtering assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='3']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx4 at 50 using my_contexts_s']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[2]/str[@name='term'][.='example with ctx2 and ctx3 at 45']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[3]/str[@name='term'][.='example with ctx1 at 40']" ); //TermQuery assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "ctx1", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='1']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx1 at 40']" ); //OR BooleanQuery assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "ctx1 OR CTX2", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='2']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx2 and ctx3 at 45']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[2]/str[@name='term'][.='example with ctx1 at 40']" ); //AND BooleanQuery assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "CTX2 AND CTX3", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='1']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx2 and ctx3 at 45']"); //PrefixQuery assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "ctx*", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='1']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx1 at 40']" ); //RangeQuery assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "[* TO *]", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='2']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx2 and ctx3 at 45']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[2]/str[@name='term'][.='example with ctx1 at 40']" ); //WildcardQuery assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "c*1", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='1']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='example with ctx1 at 40']"); } @Test public void testStringContext(){ //Here, the context field is a string, so it's case sensitive assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester_string", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "Ctx4", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester_string']/lst[@name='examp']/int[@name='numFound'][.='0']"); assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester_string", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "ctx4", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester_string']/lst[@name='examp']/int[@name='numFound'][.='1']"); } @Test public void testContextFilterOnInvalidFieldGivesNoSuggestions() throws Exception { assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "some_invalid_context_field:some_invalid_value", SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='0']"); } @Test public void testContextFilterUsesAnalyzer() throws Exception { assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "CTx1", // Will not match due to case SuggesterParams.SUGGEST_Q, "examp"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='examp']/int[@name='numFound'][.='0']"); } @Ignore// TODO: SOLR-7964 @Test public void testContextFilterWithHighlight() throws Exception { assertQ(req("qt", rh, SuggesterParams.SUGGEST_BUILD, "true", SuggesterParams.SUGGEST_DICT, "suggest_blended_infix_suggester", SuggesterParams.SUGGEST_CONTEXT_FILTER_QUERY, "ctx1", SuggesterParams.SUGGEST_HIGHLIGHT, "true", SuggesterParams.SUGGEST_Q, "example"), "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='example']/int[@name='numFound'][.='1']", "//lst[@name='suggest']/lst[@name='suggest_blended_infix_suggester']/lst[@name='example']/arr[@name='suggestions']/lst[1]/str[@name='term'][.='<b>example</b> data']" ); } }