001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.solr.search;
017:
018: import junit.framework.TestCase;
019: import org.apache.lucene.search.TermQuery;
020: import org.apache.lucene.search.BooleanQuery;
021: import org.apache.lucene.search.BooleanClause;
022: import org.apache.lucene.search.Query;
023: import org.apache.lucene.index.Term;
024: import org.apache.solr.util.AbstractSolrTestCase;
025:
026: import java.util.List;
027:
028: /**
029: * @author yonik
030: * @version $Id: TestQueryUtils.java 542653 2007-05-29 21:11:35Z yonik $
031: */
032: public class TestQueryUtils extends AbstractSolrTestCase {
033:
034: public String getSchemaFile() {
035: return "schema.xml";
036: }
037:
038: public String getSolrConfigFile() {
039: return "solrconfig.xml";
040: }
041:
042: public void setUp() throws Exception {
043: super .setUp();
044: }
045:
046: public void tearDown() throws Exception {
047: super .tearDown();
048: }
049:
050: public void positive(Query q) {
051: assertFalse(QueryUtils.isNegative(q));
052: assertTrue(QueryUtils.getAbs(q) == q);
053: List<BooleanClause> clauses = (q instanceof BooleanQuery) ? ((BooleanQuery) q)
054: .clauses()
055: : null;
056: if (clauses != null) {
057: if (clauses.size() != 0) {
058: assertTrue(QueryUtils.makeQueryable(q) == q);
059: }
060: } else {
061: assertTrue(QueryUtils.makeQueryable(q) == q);
062: }
063: }
064:
065: public void negative(Query q) {
066: assertTrue(QueryUtils.isNegative(q));
067: Query abs = QueryUtils.getAbs(q);
068: assertTrue(q != abs);
069: Query neg2 = QueryUtils.fixNegativeQuery(q);
070:
071: assertFalse(abs.equals(q));
072: assertFalse(neg2.equals(q));
073: }
074:
075: public void testNegativeQueries() {
076: TermQuery tq = new TermQuery(new Term("hi", "there"));
077: TermQuery tq2 = new TermQuery(new Term("wow", "dude"));
078: BooleanQuery bq = new BooleanQuery();
079:
080: positive(tq);
081: // positive(bq);
082: bq.add(tq, BooleanClause.Occur.SHOULD);
083: positive(bq);
084: bq.add(tq2, BooleanClause.Occur.MUST_NOT);
085: positive(bq);
086:
087: bq = new BooleanQuery();
088: bq.add(tq, BooleanClause.Occur.MUST_NOT);
089: negative(bq);
090:
091: bq.add(tq2, BooleanClause.Occur.MUST_NOT);
092: negative(bq);
093:
094: String f = "name"; // name is whitespace tokenized
095:
096: assertU(adoc("id", "1", f, "A"));
097: assertU(adoc("id", "2", f, "B"));
098: assertU(adoc("id", "3", f, "C"));
099: assertU(adoc("id", "4", f, "C"));
100: assertU(adoc("id", "5", f, "D"));
101: assertU(adoc("id", "6", f, "E"));
102: assertU(adoc("id", "7", f, "E"));
103: assertU(adoc("id", "8", f, "E W"));
104: assertU(adoc("id", "9", f, "F W"));
105: assertU(adoc("id", "10", f, "G W"));
106: assertU(adoc("id", "11", f, "G X "));
107: assertU(adoc("id", "12", f, "G X Y"));
108: assertU(adoc("id", "13", f, "G X Y Z"));
109: assertU(adoc("id", "14", f, "G Y Z"));
110: assertU(adoc("id", "15", f, "G Z"));
111: assertU(adoc("id", "16", f, "G"));
112: assertU(commit());
113:
114: assertQ("test negative base q matching nothing",
115: req("-qlkciyopsbgzyvkylsjhchghjrdf"),
116: "//result[@numFound='16']");
117:
118: assertQ("test negative base q matching something",
119: req("-name:E"), "//result[@numFound='13']");
120:
121: assertQ("test negative base q with two terms",
122: req("-name:G -name:W"), "//result[@numFound='7']");
123:
124: assertQ("test negative base q with three terms",
125: req("-name:G -name:W -name:E"),
126: "//result[@numFound='5']");
127:
128: assertQ("test negative boolean query",
129: req("-(name:G OR name:W)"), "//result[@numFound='7']");
130:
131: assertQ("test non negative q",
132: req("-name:G -name:W -name:E id:[* TO *]"),
133: "//result[@numFound='5']");
134:
135: assertQ("test non negative q",
136: req("-name:G -name:W -name:E +id:[* TO *]"),
137: "//result[@numFound='5']");
138:
139: // now for the filters...
140: assertQ("test negative base q matching nothing, with filters",
141: req("q", "-qlkciyopsbgzyvkylsjhchghjrdf", "fq",
142: "name:A"), "//result[@numFound='1']");
143:
144: assertQ("test negative filters", req("q", "name:A", "fq",
145: "-name:A"), "//result[@numFound='0']");
146: assertQ("test negative filters", req("q", "name:A", "fq",
147: "-name:A"), "//result[@numFound='0']");
148: assertQ("test negative filters", req("q", "-name:E", "fq",
149: "name:E"), "//result[@numFound='0']");
150: assertQ("test negative filters", req("q", "-name:E", "fq",
151: "name:W"), "//result[@numFound='2']");
152: assertQ("test negative filters", req("q", "-name:E", "fq",
153: "name:W"), "//result[@numFound='2']");
154: assertQ("one pos filter, one neg", req("q", "-name:E", "fq",
155: "name:W", "fq", "-name:G"), "//result[@numFound='1']");
156: assertQ("two neg filters", req("q", "-name:E", "fq", "-name:W",
157: "fq", "-name:G"), "//result[@numFound='5']" // ABCCD
158: );
159:
160: assertQ("three neg filters", req("q", "-name:E", "fq",
161: "-name:W", "fq", "-name:G", "fq", "-name:C"),
162: "//result[@numFound='3']" // ABD
163: );
164:
165: assertQ("compound neg filters", req("q", "-name:E", "fq",
166: "-name:W -name:G", "fq", "-name:C"),
167: "//result[@numFound='3']" // ABD
168: );
169:
170: assertQ("compound neg filters", req("q", "-name:E", "fq",
171: "-name:W -name:G -name:C"), "//result[@numFound='3']" // ABD
172: );
173:
174: assertQ("compound neg filters", req("q", "-name:E", "fq",
175: "-(name:W name:G name:C)"), "//result[@numFound='3']" // ABD
176: );
177:
178: assertQ("three neg filters + pos", req("q", "-name:E", "fq",
179: "-name:W", "fq", "-name:G", "fq", "-name:C", "fq",
180: "name:G"), "//result[@numFound='0']");
181: assertQ("three neg filters + pos", req("q", "-name:E", "fq",
182: "-name:W", "fq", "-name:G", "fq", "-name:C", "fq",
183: "+id:1"), "//result[@numFound='1']" // A
184: );
185: assertQ("three neg filters + pos", req("q", "-name:E", "fq",
186: "-name:W", "fq", "-name:G", "fq", "-name:C", "fq",
187: "id:[* TO *]"), "//result[@numFound='3']" // ABD
188: );
189:
190: // QueryParser turns term queries on stopwords into a BooleanQuery with
191: // zero clauses.
192: assertQ("neg base query on stopword", req("q",
193: "-text:stopworda"), "//result[@numFound='16']" // ABD
194: );
195:
196: assertQ("negative filter on stopword", req("q", "id:[* TO *]",
197: "fq", "-text:stopworda"), "//result[@numFound='16']" // ABD
198: );
199: assertQ("two negative filters on stopword", req("q",
200: "id:[* TO *]", "fq", "-text:stopworda", "fq",
201: "-text:stopworda"), "//result[@numFound='16']" // ABD
202: );
203: assertQ("compound negative filters with stopword", req("q",
204: "id:[* TO *]", "fq", "-text:stopworda -id:1"),
205: "//result[@numFound='15']" // ABD
206: );
207: }
208:
209: }
|