org.apache.solr.util.SolrPluginUtilsTest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.solr.util.SolrPluginUtilsTest.java

Source

/*
 * 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.util;

import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.QParser;
import org.apache.solr.util.SolrPluginUtils.DisjunctionMaxQueryParser;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.DocList;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;

import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;

/**
 * Tests that the functions in SolrPluginUtils work as advertised.
 */
public class SolrPluginUtilsTest extends SolrTestCaseJ4 {

    @BeforeClass
    public static void beforeClass() throws Exception {
        initCore("solrconfig.xml", "schema.xml");
    }

    @Test
    public void testDocListConversion() throws Exception {
        assertU("", adoc("id", "3234", "val_i", "1", "val_dynamic", "quick red fox"));
        assertU("", adoc("id", "3235", "val_i", "1", "val_dynamic", "quick green fox"));
        assertU("", adoc("id", "3236", "val_i", "1", "val_dynamic", "quick brown fox"));
        assertU("", commit());

        RefCounted<SolrIndexSearcher> holder = h.getCore().getSearcher();
        try {
            SolrIndexSearcher srchr = holder.get();
            SolrIndexSearcher.QueryResult qr = new SolrIndexSearcher.QueryResult();
            SolrIndexSearcher.QueryCommand cmd = new SolrIndexSearcher.QueryCommand();
            cmd.setQuery(new MatchAllDocsQuery());
            cmd.setLen(10);
            qr = srchr.search(qr, cmd);

            DocList docs = qr.getDocList();
            assertEquals("wrong docs size", 3, docs.size());
            Set<String> fields = new HashSet<String>();
            fields.add("val_dynamic");
            fields.add("dynamic_val");
            fields.add("range_facet_l"); // copied from id

            SolrDocumentList list = SolrPluginUtils.docListToSolrDocumentList(docs, srchr, fields, null);
            assertEquals("wrong list Size", docs.size(), list.size());
            for (SolrDocument document : list) {

                assertTrue("unexpected field", !document.containsKey("val_i"));
                assertTrue("unexpected id field", !document.containsKey("id"));

                assertTrue("original field", document.containsKey("val_dynamic"));
                assertTrue("dyn copy field", document.containsKey("dynamic_val"));
                assertTrue("copy field", document.containsKey("range_facet_l"));

                assertNotNull("original field null", document.get("val_dynamic"));
                assertNotNull("dyn copy field null", document.get("dynamic_val"));
                assertNotNull("copy field null", document.get("range_facet_l"));
            }
        } finally {
            if (null != holder)
                holder.decref();
        }
    }

    @Test
    public void testPartialEscape() {

        assertEquals("", pe(""));
        assertEquals("foo", pe("foo"));
        assertEquals("foo\\:bar", pe("foo:bar"));
        assertEquals("+foo\\:bar", pe("+foo:bar"));
        assertEquals("foo \\! bar", pe("foo ! bar"));
        assertEquals("foo\\?", pe("foo?"));
        assertEquals("foo \"bar\"", pe("foo \"bar\""));
        assertEquals("foo\\! \"bar\"", pe("foo! \"bar\""));

    }

    @Test
    public void testStripUnbalancedQuotes() {

        assertEquals("", strip(""));
        assertEquals("foo", strip("foo"));
        assertEquals("foo \"bar\"", strip("foo \"bar\""));
        assertEquals("42", strip("42\""));
        assertEquals("\"how now brown cow?\"", strip("\"how now brown cow?\""));
        assertEquals("\"you go\" \"now!\"", strip("\"you go\" \"now!\""));

    }

    @Test
    public void testStripIllegalOperators() {

        assertEquals("", stripOp(""));
        assertEquals("foo", stripOp("foo"));
        assertEquals("foo -bar", stripOp("foo -bar"));
        assertEquals("foo +bar", stripOp("foo +bar"));
        assertEquals("foo + bar", stripOp("foo + bar"));
        assertEquals("foo+ bar", stripOp("foo+ bar"));
        assertEquals("foo+ bar", stripOp("foo+ bar"));
        assertEquals("foo+", stripOp("foo+"));
        assertEquals("foo bar", stripOp("foo bar -"));
        assertEquals("foo bar ", stripOp("foo bar - + ++"));
        assertEquals("foo bar", stripOp("foo --bar"));
        assertEquals("foo bar ", stripOp(
                "foo -------------------------------------------------------------------------------------------------------------------------bar --"));
        assertEquals("foo bar ", stripOp(
                "foo --bar -----------------------------------------------------------------------------------------------------------------------"));

    }

    @Test
    public void testParseFieldBoosts() throws Exception {

        Map<String, Float> e1 = new HashMap<String, Float>();
        e1.put("fieldOne", 2.3f);
        e1.put("fieldTwo", null);
        e1.put("fieldThree", -0.4f);

        assertEquals("basic e1", e1, SolrPluginUtils.parseFieldBoosts("fieldOne^2.3 fieldTwo fieldThree^-0.4"));
        assertEquals("spacey e1", e1,
                SolrPluginUtils.parseFieldBoosts("  fieldOne^2.3   fieldTwo fieldThree^-0.4   "));
        assertEquals("really spacey e1", e1,
                SolrPluginUtils.parseFieldBoosts(" \t fieldOne^2.3 \n  fieldTwo fieldThree^-0.4   "));
        assertEquals("really spacey e1", e1, SolrPluginUtils
                .parseFieldBoosts(new String[] { " \t fieldOne^2.3 \n", "  fieldTwo fieldThree^-0.4   ", " " }));

        Map<String, Float> e2 = new HashMap<String, Float>();
        assertEquals("empty e2", e2, SolrPluginUtils.parseFieldBoosts(""));
        assertEquals("spacey e2", e2, SolrPluginUtils.parseFieldBoosts("   \t   "));
    }

    @Test
    public void testDisjunctionMaxQueryParser() throws Exception {

        Query out;
        String t;

        SolrQueryRequest req = req();
        QParser qparser = QParser.getParser("hi", "dismax", req);

        DisjunctionMaxQueryParser qp = new SolrPluginUtils.DisjunctionMaxQueryParser(qparser,
                req.getSchema().getDefaultSearchFieldName());

        qp.addAlias("hoss", 0.01f,
                SolrPluginUtils.parseFieldBoosts("title^2.0 title_stemmed name^1.2 subject^0.5"));
        qp.addAlias("test", 0.01f, SolrPluginUtils.parseFieldBoosts("text^2.0"));
        qp.addAlias("unused", 1.0f, SolrPluginUtils.parseFieldBoosts("subject^0.5 sind^1.5"));

        /* first some sanity tests that don't use aliasing at all */

        t = "XXXXXXXX";
        out = qp.parse(t);
        assertNotNull(t + " sanity test gave back null", out);
        assertTrue(t + " sanity test isn't TermQuery: " + out.getClass(), out instanceof TermQuery);
        assertEquals(t + " sanity test is wrong field", h.getCore().getLatestSchema().getDefaultSearchFieldName(),
                ((TermQuery) out).getTerm().field());

        t = "subject:XXXXXXXX";
        out = qp.parse(t);
        assertNotNull(t + " sanity test gave back null", out);
        assertTrue(t + " sanity test isn't TermQuery: " + out.getClass(), out instanceof TermQuery);
        assertEquals(t + " sanity test is wrong field", "subject", ((TermQuery) out).getTerm().field());

        /* field has untokenzied type, so this should be a term anyway */
        t = "sind:\"simple phrase\"";
        out = qp.parse(t);
        assertNotNull(t + " sanity test gave back null", out);
        assertTrue(t + " sanity test isn't TermQuery: " + out.getClass(), out instanceof TermQuery);
        assertEquals(t + " sanity test is wrong field", "sind", ((TermQuery) out).getTerm().field());

        t = "subject:\"simple phrase\"";
        out = qp.parse(t);
        assertNotNull(t + " sanity test gave back null", out);
        assertTrue(t + " sanity test isn't PhraseQuery: " + out.getClass(), out instanceof PhraseQuery);
        assertEquals(t + " sanity test is wrong field", "subject", ((PhraseQuery) out).getTerms()[0].field());

        /* now some tests that use aliasing */

        /* basic usage of single "term" */
        t = "hoss:XXXXXXXX";
        out = qp.parse(t);
        assertNotNull(t + " was null", out);
        assertTrue(t + " wasn't a DMQ:" + out.getClass(), out instanceof DisjunctionMaxQuery);
        assertEquals(t + " wrong number of clauses", 4, countItems(((DisjunctionMaxQuery) out).iterator()));

        /* odd case, but should still work, DMQ of one clause */
        t = "test:YYYYY";
        out = qp.parse(t);
        assertNotNull(t + " was null", out);
        assertTrue(t + " wasn't a DMQ:" + out.getClass(), out instanceof DisjunctionMaxQuery);
        assertEquals(t + " wrong number of clauses", 1, countItems(((DisjunctionMaxQuery) out).iterator()));

        /* basic usage of multiple "terms" */
        t = "hoss:XXXXXXXX test:YYYYY";
        out = qp.parse(t);
        assertNotNull(t + " was null", out);
        assertTrue(t + " wasn't a boolean:" + out.getClass(), out instanceof BooleanQuery);
        {
            BooleanQuery bq = (BooleanQuery) out;
            List<BooleanClause> clauses = bq.clauses();
            assertEquals(t + " wrong number of clauses", 2, clauses.size());
            Query sub = clauses.get(0).getQuery();
            assertTrue(t + " first wasn't a DMQ:" + sub.getClass(), sub instanceof DisjunctionMaxQuery);
            assertEquals(t + " first had wrong number of clauses", 4,
                    countItems(((DisjunctionMaxQuery) sub).iterator()));
            sub = clauses.get(1).getQuery();
            assertTrue(t + " second wasn't a DMQ:" + sub.getClass(), sub instanceof DisjunctionMaxQuery);
            assertEquals(t + " second had wrong number of clauses", 1,
                    countItems(((DisjunctionMaxQuery) sub).iterator()));
        }

        /* a phrase, and a term that is a stop word for some fields */
        t = "hoss:\"XXXXXX YYYYY\" hoss:the";
        out = qp.parse(t);
        assertNotNull(t + " was null", out);
        assertTrue(t + " wasn't a boolean:" + out.getClass(), out instanceof BooleanQuery);
        {
            BooleanQuery bq = (BooleanQuery) out;
            List<BooleanClause> clauses = bq.clauses();
            assertEquals(t + " wrong number of clauses", 2, clauses.size());
            Query sub = clauses.get(0).getQuery();
            assertTrue(t + " first wasn't a DMQ:" + sub.getClass(), sub instanceof DisjunctionMaxQuery);
            assertEquals(t + " first had wrong number of clauses", 4,
                    countItems(((DisjunctionMaxQuery) sub).iterator()));
            sub = clauses.get(1).getQuery();
            assertTrue(t + " second wasn't a DMQ:" + sub.getClass(), sub instanceof DisjunctionMaxQuery);
            assertEquals(t + " second had wrong number of clauses (stop words)", 2,
                    countItems(((DisjunctionMaxQuery) sub).iterator()));
        }

    }

    private static int countItems(Iterator i) {
        int count = 0;
        while (i.hasNext()) {
            count++;
            i.next();
        }
        return count;
    }

    @Test
    public void testMinShouldMatchCalculator() {

        /* zero is zero is zero */
        assertEquals(0, calcMSM(5, "0"));
        assertEquals(0, calcMSM(5, "0%"));
        assertEquals(0, calcMSM(5, " -5 "));
        assertEquals(0, calcMSM(5, "\n -100% \n"));

        /* basic integers */
        assertEquals(3, calcMSM(5, " \n3\n "));
        assertEquals(2, calcMSM(5, "-3"));
        assertEquals(3, calcMSM(3, "3"));
        assertEquals(0, calcMSM(3, "-3"));
        assertEquals(3, calcMSM(3, "5"));
        assertEquals(0, calcMSM(3, "-5"));

        /* positive percentages with rounding */
        assertEquals(0, calcMSM(3, " \n25% \n"));
        assertEquals(1, calcMSM(4, "25%"));
        assertEquals(1, calcMSM(5, " 25% "));
        assertEquals(2, calcMSM(10, "25%"));

        /* negative percentages with rounding */
        assertEquals(3, calcMSM(3, " \n-25%\n "));
        assertEquals(3, calcMSM(4, "-25%"));
        assertEquals(4, calcMSM(5, "-25%"));
        assertEquals(8, calcMSM(10, "-25%"));

        /* conditional */
        assertEquals(1, calcMSM(1, "3<0"));
        assertEquals(2, calcMSM(2, "3<0"));
        assertEquals(3, calcMSM(3, "3<0"));
        assertEquals(0, calcMSM(4, "3<0"));
        assertEquals(0, calcMSM(5, "3<0"));
        assertEquals(1, calcMSM(1, "3<25%"));
        assertEquals(2, calcMSM(2, " 3\n<\n25% "));
        assertEquals(3, calcMSM(3, "3<25%"));
        assertEquals(1, calcMSM(4, "\n 3 < \n25%\n "));
        assertEquals(1, calcMSM(5, "3<25%"));

        /* multiple conditionals */
        assertEquals(1, calcMSM(1, "\n3 < -25% 10 < -3 \n"));
        assertEquals(2, calcMSM(2, " 3 < -25% 10 < -3\n"));
        assertEquals(3, calcMSM(3, " 3 < -25% \n 10 < -3 \n"));
        assertEquals(3, calcMSM(4, " 3 < -25% 10 < -3 "));
        assertEquals(4, calcMSM(5, " 3 < -25% 10 < -3"));
        assertEquals(5, calcMSM(6, "3<-25% 10<-3"));
        assertEquals(6, calcMSM(7, " 3 < -25% 10 < -3 "));
        assertEquals(6, calcMSM(8, " 3 < -25% 10 \n < -3\n"));
        assertEquals(7, calcMSM(9, " 3 < -25% 10 < -3 \n"));
        assertEquals(8, calcMSM(10, " 3 < -25% 10 < -3"));
        assertEquals(8, calcMSM(11, "3<-25% 10<-3"));
        assertEquals(9, calcMSM(12, "3<-25% 10<-3"));
        assertEquals(97, calcMSM(100, "3<-25% 10<-3"));

        BooleanQuery q = new BooleanQuery();
        q.add(new TermQuery(new Term("a", "b")), Occur.SHOULD);
        q.add(new TermQuery(new Term("a", "c")), Occur.SHOULD);
        q.add(new TermQuery(new Term("a", "d")), Occur.SHOULD);
        q.add(new TermQuery(new Term("a", "d")), Occur.SHOULD);

        SolrPluginUtils.setMinShouldMatch(q, "0");
        assertEquals(0, q.getMinimumNumberShouldMatch());

        SolrPluginUtils.setMinShouldMatch(q, "1");
        assertEquals(1, q.getMinimumNumberShouldMatch());

        SolrPluginUtils.setMinShouldMatch(q, "50%");
        assertEquals(2, q.getMinimumNumberShouldMatch());

        SolrPluginUtils.setMinShouldMatch(q, "99");
        assertEquals(4, q.getMinimumNumberShouldMatch());

        q.add(new TermQuery(new Term("a", "e")), Occur.MUST);
        q.add(new TermQuery(new Term("a", "f")), Occur.MUST);

        SolrPluginUtils.setMinShouldMatch(q, "50%");
        assertEquals(2, q.getMinimumNumberShouldMatch());

    }

    /** macro */
    public String pe(CharSequence s) {
        return SolrPluginUtils.partialEscape(s).toString();
    }

    /** macro */
    public String strip(CharSequence s) {
        return SolrPluginUtils.stripUnbalancedQuotes(s).toString();
    }

    /** macro */
    public String stripOp(CharSequence s) {
        return SolrPluginUtils.stripIllegalOperators(s).toString();
    }

    /** macro */
    public int calcMSM(int clauses, String spec) {
        return SolrPluginUtils.calculateMinShouldMatch(clauses, spec);
    }
}