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;
017:
018: import org.apache.lucene.document.*;
019: import org.apache.lucene.search.Query;
020: import org.apache.lucene.search.BooleanQuery;
021: import org.apache.solr.core.SolrCore;
022: import org.apache.solr.search.*;
023: import org.apache.solr.handler.*;
024: import org.apache.solr.request.*;
025: import org.apache.solr.util.*;
026: import org.apache.solr.schema.*;
027:
028: import javax.xml.parsers.DocumentBuilderFactory;
029: import javax.xml.parsers.DocumentBuilder;
030: import java.io.IOException;
031: import java.io.StringWriter;
032: import java.io.ByteArrayInputStream;
033: import java.util.Map;
034: import java.util.HashMap;
035:
036: /**
037: * Tests some basic functionality of Solr while demonstrating good
038: * Best Practices for using AbstractSolrTestCase
039: */
040: public class BasicFunctionalityTest extends AbstractSolrTestCase {
041:
042: public String getSchemaFile() {
043: return "schema.xml";
044: }
045:
046: public String getSolrConfigFile() {
047: return "solrconfig.xml";
048: }
049:
050: public void setUp() throws Exception {
051: // if you override setUp or tearDown, you better call
052: // the super classes version
053: super .setUp();
054: }
055:
056: public void tearDown() throws Exception {
057: // if you override setUp or tearDown, you better call
058: // the super classes version
059: super .tearDown();
060:
061: }
062:
063: public void testIgnoredFields() throws Exception {
064: lrf.args.put("version", "2.0");
065: assertU("adding doc with ignored field", adoc("id", "42",
066: "foo_ignored", "blah blah"));
067: assertU("commit", commit());
068:
069: // :TODO: the behavior of querying on an unindexed field should be better specified in the future.
070: assertQ("query with ignored field",
071: req("bar_ignored:yo id:42"), "//*[@numFound='1']",
072: "//int[@name='id'][.='42']");
073: }
074:
075: public void testSomeStuff() throws Exception {
076: lrf.args.put("version", "2.0");
077: assertQ("test query on empty index",
078: req("qlkciyopsbgzyvkylsjhchghjrdf"),
079: "//result[@numFound='0']");
080:
081: // test escaping of ";"
082: assertU("deleting 42 for no reason at all", delI("42"));
083: assertU("adding doc#42", adoc("id", "42", "val_s", "aa;bb"));
084: assertU("does commit work?", commit());
085:
086: assertQ("backslash escaping semicolon",
087: req("id:42 AND val_s:aa\\;bb"), "//*[@numFound='1']",
088: "//int[@name='id'][.='42']");
089:
090: assertQ("quote escaping semicolon",
091: req("id:42 AND val_s:\"aa;bb\""), "//*[@numFound='1']",
092: "//int[@name='id'][.='42']");
093:
094: assertQ("no escaping semicolon", req("id:42 AND val_s:aa"),
095: "//*[@numFound='0']");
096:
097: assertU(delI("42"));
098: assertU(commit());
099: assertQ(req("id:42"), "//*[@numFound='0']");
100:
101: // test allowDups default of false
102:
103: assertU(adoc("id", "42", "val_s", "AAA"));
104: assertU(adoc("id", "42", "val_s", "BBB"));
105: assertU(commit());
106: assertQ(req("id:42"), "//*[@numFound='1']", "//str[.='BBB']");
107: assertU(adoc("id", "42", "val_s", "CCC"));
108: assertU(adoc("id", "42", "val_s", "DDD"));
109: assertU(commit());
110: assertQ(req("id:42"), "//*[@numFound='1']", "//str[.='DDD']");
111:
112: // test deletes
113: String[] adds = new String[] {
114: add(doc("id", "101"), "allowDups", "false"),
115: add(doc("id", "101"), "allowDups", "false"),
116: add(doc("id", "105"), "allowDups", "true"),
117: add(doc("id", "102"), "allowDups", "false"),
118: add(doc("id", "103"), "allowDups", "true"),
119: add(doc("id", "101"), "allowDups", "false"), };
120: for (String a : adds) {
121: assertU(a, a);
122: }
123: assertU(commit());
124: assertQ(req("id:[100 TO 110]"), "//*[@numFound='4']");
125: assertU(delI("102"));
126: assertU(commit());
127: assertQ(req("id:[100 TO 110]"), "//*[@numFound='3']");
128: assertU(delI("105"));
129: assertU(commit());
130: assertQ(req("id:[100 TO 110]"), "//*[@numFound='2']");
131: assertU(delQ("id:[100 TO 110]"));
132: assertU(commit());
133: assertQ(req("id:[100 TO 110]"), "//*[@numFound='0']");
134: }
135:
136: public void testRequestHandlerBaseException() {
137: final String tmp = "BOO!";
138: SolrRequestHandler handler = new RequestHandlerBase() {
139: public String getDescription() {
140: return tmp;
141: }
142:
143: public String getSourceId() {
144: return tmp;
145: }
146:
147: public String getSource() {
148: return tmp;
149: }
150:
151: public String getVersion() {
152: return tmp;
153: }
154:
155: public void handleRequestBody(SolrQueryRequest req,
156: SolrQueryResponse rsp) {
157: throw new RuntimeException(tmp);
158: }
159: };
160: handler.init(new NamedList());
161: SolrQueryResponse rsp = new SolrQueryResponse();
162: h.getCore()
163: .execute(
164: handler,
165: new LocalSolrQueryRequest(h.getCore(),
166: new NamedList()), rsp);
167: assertNotNull("should have found an exception", rsp
168: .getException());
169:
170: }
171:
172: public void testMultipleUpdatesPerAdd() {
173:
174: // big freaking kludge since the response is currently not well formed.
175: String res = h
176: .update("<add><doc><field name=\"id\">1</field></doc><doc><field name=\"id\">2</field></doc></add>");
177: assertEquals("<result status=\"0\"></result>", res);
178: assertU("<commit/>");
179: assertQ(req("id:[0 TO 99]"), "//*[@numFound='2']");
180:
181: }
182:
183: public void testDocBoost() throws Exception {
184: String res = h
185: .update("<add>"
186: + "<doc><field name=\"id\">1</field>"
187: + "<field name=\"text\">hello</field></doc>"
188: + "<doc boost=\"2.0\"><field name=\"id\">2</field>"
189: + "<field name=\"text\">hello</field></doc>"
190: + "</add>");
191:
192: assertEquals("<result status=\"0\"></result>", res);
193: assertU("<commit/>");
194: assertQ(req("text:hello"), "//*[@numFound='2']");
195: String resp = h.query(lrf.makeRequest("q", "text:hello",
196: "debugQuery", "true"));
197: //System.out.println(resp);
198: // second doc ranked first
199: assertTrue(resp.indexOf("id=2") < resp.indexOf("id=1"));
200: }
201:
202: public void testFieldBoost() throws Exception {
203: String res = h
204: .update("<add>"
205: + "<doc><field name=\"id\">1</field>"
206: + "<field name=\"text\">hello</field></doc>"
207: + "<doc><field name=\"id\">2</field>"
208: + "<field boost=\"2.0\" name=\"text\">hello</field></doc>"
209: + "</add>");
210:
211: assertEquals("<result status=\"0\"></result>", res);
212: assertU("<commit/>");
213: assertQ(req("text:hello"), "//*[@numFound='2']");
214: String resp = h.query(lrf.makeRequest("q", "text:hello",
215: "debugQuery", "true"));
216: //System.out.println(resp);
217: // second doc ranked first
218: assertTrue(resp.indexOf("id=2") < resp.indexOf("id=1"));
219: }
220:
221: public void testXMLWriter() throws Exception {
222:
223: SolrQueryResponse rsp = new SolrQueryResponse();
224: rsp.add("\"quoted\"", "\"value\"");
225:
226: StringWriter writer = new StringWriter(32000);
227: XMLWriter.writeResponse(writer, req("foo"), rsp);
228:
229: DocumentBuilder builder = DocumentBuilderFactory.newInstance()
230: .newDocumentBuilder();
231: builder.parse(new ByteArrayInputStream(writer.toString()
232: .getBytes("UTF-8")));
233: }
234:
235: public void testLocalSolrQueryRequestParams() {
236: HashMap args = new HashMap();
237: args.put("string", "string value");
238: args.put("array", new String[] { "array", "value" });
239: SolrQueryRequest req = new LocalSolrQueryRequest(null, null,
240: null, 0, 20, args);
241: assertEquals("string value", req.getParam("string"));
242: assertEquals("array", req.getParam("array"));
243:
244: String[] stringParams = req.getParams("string");
245: assertEquals(1, stringParams.length);
246: assertEquals("string value", stringParams[0]);
247:
248: String[] arrayParams = req.getParams("array");
249: assertEquals(2, arrayParams.length);
250: assertEquals("array", arrayParams[0]);
251: assertEquals("value", arrayParams[1]);
252: }
253:
254: public void testKeywordTokenizerFactory() {
255:
256: assertU(adoc("id", "42", "keywordtok",
257: "How nOw broWn-ish C.o.w. ?"));
258: assertU(commit());
259: assertQ("stored value matches?", req("id:42"),
260: "//str[.='How nOw broWn-ish C.o.w. ?']");
261: assertQ("query on exact matches?",
262: req("keywordtok:\"How nOw broWn-ish C.o.w. ?\""),
263: "//str[.='How nOw broWn-ish C.o.w. ?']");
264: }
265:
266: /** @see org.apache.solr.analysis.TestRemoveDuplicatesTokenFilter */
267: public void testRemoveDuplicatesTokenFilter() {
268: Query q = QueryParsing.parseQuery("TV", "dedup", h.getCore()
269: .getSchema());
270: assertTrue("not boolean?", q instanceof BooleanQuery);
271: assertEquals("unexpected number of stemmed synonym tokens", 2,
272: ((BooleanQuery) q).clauses().size());
273: }
274:
275: public void testTermVectorFields() {
276:
277: IndexSchema ischema = new IndexSchema(getSchemaFile());
278: SchemaField f; // Solr field type
279: Field luf; // Lucene field
280:
281: f = ischema.getField("test_basictv");
282: luf = f.createField("test", 0f);
283: assertTrue(f.storeTermVector());
284: assertTrue(luf.isTermVectorStored());
285:
286: f = ischema.getField("test_notv");
287: luf = f.createField("test", 0f);
288: assertTrue(!f.storeTermVector());
289: assertTrue(!luf.isTermVectorStored());
290:
291: f = ischema.getField("test_postv");
292: luf = f.createField("test", 0f);
293: assertTrue(f.storeTermVector() && f.storeTermPositions());
294: assertTrue(luf.isStorePositionWithTermVector());
295:
296: f = ischema.getField("test_offtv");
297: luf = f.createField("test", 0f);
298: assertTrue(f.storeTermVector() && f.storeTermOffsets());
299: assertTrue(luf.isStoreOffsetWithTermVector());
300:
301: f = ischema.getField("test_posofftv");
302: luf = f.createField("test", 0f);
303: assertTrue(f.storeTermVector() && f.storeTermPositions()
304: && f.storeTermOffsets());
305: assertTrue(luf.isStoreOffsetWithTermVector()
306: && luf.isStorePositionWithTermVector());
307:
308: }
309:
310: public void testSolrParams() throws Exception {
311: NamedList nl = new NamedList();
312: nl.add("i", 555);
313: nl.add("s", "bbb");
314: nl.add("bt", "true");
315: nl.add("bf", "false");
316:
317: Map<String, String> m = new HashMap<String, String>();
318: m.put("f.field1.i", "1000");
319: m.put("s", "BBB");
320: m.put("ss", "SSS");
321:
322: LocalSolrQueryRequest req = new LocalSolrQueryRequest(null, nl);
323: SolrParams p = req.getParams();
324:
325: assertEquals(p.get("i"), "555");
326: assertEquals(p.getInt("i").intValue(), 555);
327: assertEquals(p.getInt("i", 5), 555);
328: assertEquals(p.getInt("iii", 5), 5);
329: assertEquals(p.getFieldParam("field1", "i"), "555");
330:
331: req.setParams(new DefaultSolrParams(p, new MapSolrParams(m)));
332: p = req.getParams();
333: assertEquals(req.getOriginalParams().get("s"), "bbb");
334: assertEquals(p.get("i"), "555");
335: assertEquals(p.getInt("i").intValue(), 555);
336: assertEquals(p.getInt("i", 5), 555);
337: assertEquals(p.getInt("iii", 5), 5);
338:
339: assertEquals(p.getFieldParam("field1", "i"), "1000");
340: assertEquals(p.get("s"), "bbb");
341: assertEquals(p.get("ss"), "SSS");
342:
343: assertEquals(!!p.getBool("bt"), !p.getBool("bf"));
344: assertEquals(p.getBool("foo", true), true);
345: assertEquals(p.getBool("foo", false), false);
346: assertEquals(!!p.getBool("bt"), !p.getBool("bf"));
347:
348: NamedList more = new NamedList();
349: more.add("s", "aaa");
350: more.add("s", "ccc");
351: more.add("ss", "YYY");
352: more.add("xx", "XXX");
353: p = new AppendedSolrParams(p, SolrParams.toSolrParams(more));
354: assertEquals(3, p.getParams("s").length);
355: assertEquals("bbb", p.getParams("s")[0]);
356: assertEquals("aaa", p.getParams("s")[1]);
357: assertEquals("ccc", p.getParams("s")[2]);
358: assertEquals(3, p.getParams("s").length);
359: assertEquals("SSS", p.get("ss"));
360: assertEquals("XXX", p.get("xx"));
361:
362: }
363:
364: public void testDefaultFieldValues() {
365:
366: assertU(adoc("id", "4055", "subject",
367: "Hoss the Hoss man Hostetter"));
368: assertU(adoc("id", "4056", "intDefault", "4", "subject",
369: "Some Other Guy"));
370: assertU(adoc("id", "4057", "multiDefault", "a", "multiDefault",
371: "b", "subject", "The Dude"));
372: assertU(commit());
373:
374: assertQ("everthing should have recent timestamp",
375: req("timestamp:[NOW-10MINUTES TO NOW]"),
376: "*[count(//doc)=3]", "//date[@name='timestamp']");
377:
378: assertQ("2 docs should have the default for multiDefault",
379: req("multiDefault:muLti-Default"), "*[count(//doc)=2]",
380: "//arr[@name='multiDefault']");
381: assertQ("1 doc should have it's explicit multiDefault",
382: req("multiDefault:a"), "*[count(//doc)=1]");
383:
384: assertQ("2 docs should have the default for intDefault",
385: req("intDefault:42"), "*[count(//doc)=2]");
386: assertQ("1 doc should have it's explicit intDefault",
387: req("intDefault:[3 TO 5]"), "*[count(//doc)=1]");
388:
389: }
390:
391: public void testConfigDefaults() {
392: assertU(adoc("id", "42", "name", "Zapp Brannigan"));
393: assertU(adoc("id", "43", "title", "Democratic Order of Planets"));
394: assertU(adoc("id", "44", "name", "The Zapper"));
395: assertU(adoc("id", "45", "title", "25 star General"));
396: assertU(adoc("id", "46", "subject",
397: "Defeated the pacifists of the Gandhi nebula"));
398: assertU(adoc(
399: "id",
400: "47",
401: "text",
402: "line up and fly directly at the enemy death cannons, clogging them with wreckage!"));
403: assertU(commit());
404:
405: assertQ("standard request handler returns all matches",
406: req("id:[42 TO 47]"), "*[count(//doc)=6]");
407:
408: assertQ("defaults handler returns fewer matches", req("q",
409: "id:[42 TO 47]", "qt", "defaults"), "*[count(//doc)=4]");
410:
411: assertQ("defaults handler includes highlighting", req("q",
412: "name:Zapp OR title:General", "qt", "defaults"),
413: "//lst[@name='highlighting']");
414:
415: }
416:
417: public void testSimpleFacetCounts() {
418: assertU(adoc("id", "42", "trait_s", "Tool", "trait_s",
419: "Obnoxious", "name", "Zapp Brannigan"));
420: assertU(adoc("id", "43", "title", "Democratic Order of Planets"));
421: assertU(adoc("id", "44", "trait_s", "Tool", "name",
422: "The Zapper"));
423: assertU(adoc("id", "45", "trait_s", "Chauvinist", "title",
424: "25 star General"));
425: assertU(adoc("id", "46", "trait_s", "Obnoxious", "subject",
426: "Defeated the pacifists of the Gandhi nebula"));
427: assertU(adoc(
428: "id",
429: "47",
430: "trait_s",
431: "Pig",
432: "text",
433: "line up and fly directly at the enemy death cannons, clogging them with wreckage!"));
434: assertU(commit());
435:
436: assertQ("standard request handler returns all matches",
437: req("id:[42 TO 47]"), "*[count(//doc)=6]");
438:
439: assertQ("filter results using fq", req("q", "id:[42 TO 46]",
440: "fq", "id:[43 TO 47]"), "*[count(//doc)=4]");
441:
442: assertQ("don't filter results using blank fq", req("q",
443: "id:[42 TO 46]", "fq", " "), "*[count(//doc)=5]");
444:
445: assertQ("filter results using multiple fq params", req("q",
446: "id:[42 TO 46]", "fq", "trait_s:Obnoxious", "fq",
447: "id:[43 TO 47]"), "*[count(//doc)=1]");
448:
449: assertQ(
450: "check counts for facet queries",
451: req("q", "id:[42 TO 47]", "facet", "true",
452: "facet.query", "trait_s:Obnoxious",
453: "facet.query", "id:[42 TO 45]", "facet.query",
454: "id:[43 TO 47]", "facet.field", "trait_s"),
455: "*[count(//doc)=6]"
456:
457: ,
458: "//lst[@name='facet_counts']/lst[@name='facet_queries']",
459: "//lst[@name='facet_queries']/int[@name='trait_s:Obnoxious'][.='2']",
460: "//lst[@name='facet_queries']/int[@name='id:[42 TO 45]'][.='4']",
461: "//lst[@name='facet_queries']/int[@name='id:[43 TO 47]'][.='5']"
462:
463: ,
464: "//lst[@name='facet_counts']/lst[@name='facet_fields']",
465: "//lst[@name='facet_fields']/lst[@name='trait_s']",
466: "*[count(//lst[@name='trait_s']/int)=4]",
467: "//lst[@name='trait_s']/int[@name='Tool'][.='2']",
468: "//lst[@name='trait_s']/int[@name='Obnoxious'][.='2']",
469: "//lst[@name='trait_s']/int[@name='Pig'][.='1']");
470:
471: assertQ(
472: "check counts for applied facet queries using filtering (fq)",
473: req("q", "id:[42 TO 47]", "facet", "true", "fq",
474: "id:[42 TO 45]", "facet.field", "trait_s",
475: "facet.query", "id:[42 TO 45]", "facet.query",
476: "id:[43 TO 47]"),
477: "*[count(//doc)=4]",
478: "//lst[@name='facet_counts']/lst[@name='facet_queries']",
479: "//lst[@name='facet_queries']/int[@name='id:[42 TO 45]'][.='4']",
480: "//lst[@name='facet_queries']/int[@name='id:[43 TO 47]'][.='3']",
481: "*[count(//lst[@name='trait_s']/int)=4]",
482: "//lst[@name='trait_s']/int[@name='Tool'][.='2']",
483: "//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']",
484: "//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']",
485: "//lst[@name='trait_s']/int[@name='Pig'][.='0']");
486:
487: assertQ(
488: "check counts with facet.zero=false&facet.missing=true using fq",
489: req("q", "id:[42 TO 47]", "facet", "true",
490: "facet.zeros", "false",
491: "f.trait_s.facet.missing", "true", "fq",
492: "id:[42 TO 45]", "facet.field", "trait_s"),
493: "*[count(//doc)=4]",
494: "*[count(//lst[@name='trait_s']/int)=4]",
495: "//lst[@name='trait_s']/int[@name='Tool'][.='2']",
496: "//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']",
497: "//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']",
498: "//lst[@name='trait_s']/int[not(@name)][.='1']");
499:
500: assertQ(
501: "check counts with facet.mincount=1&facet.missing=true using fq",
502: req("q", "id:[42 TO 47]", "facet", "true",
503: "facet.mincount", "1",
504: "f.trait_s.facet.missing", "true", "fq",
505: "id:[42 TO 45]", "facet.field", "trait_s"),
506: "*[count(//doc)=4]",
507: "*[count(//lst[@name='trait_s']/int)=4]",
508: "//lst[@name='trait_s']/int[@name='Tool'][.='2']",
509: "//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']",
510: "//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']",
511: "//lst[@name='trait_s']/int[not(@name)][.='1']");
512:
513: assertQ(
514: "check counts with facet.mincount=2&facet.missing=true using fq",
515: req("q", "id:[42 TO 47]", "facet", "true",
516: "facet.mincount", "2",
517: "f.trait_s.facet.missing", "true", "fq",
518: "id:[42 TO 45]", "facet.field", "trait_s"),
519: "*[count(//doc)=4]",
520: "*[count(//lst[@name='trait_s']/int)=2]",
521: "//lst[@name='trait_s']/int[@name='Tool'][.='2']",
522: "//lst[@name='trait_s']/int[not(@name)][.='1']");
523:
524: assertQ(
525: "check sorted paging",
526: req("q", "id:[42 TO 47]", "facet", "true", "fq",
527: "id:[42 TO 45]", "facet.field", "trait_s",
528: "facet.mincount", "0", "facet.offset", "0",
529: "facet.limit", "4"),
530: "*[count(//lst[@name='trait_s']/int)=4]",
531: "//lst[@name='trait_s']/int[@name='Tool'][.='2']",
532: "//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']",
533: "//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']",
534: "//lst[@name='trait_s']/int[@name='Pig'][.='0']");
535:
536: assertQ("check sorted paging", req("q", "id:[42 TO 47]",
537: "facet", "true", "fq", "id:[42 TO 45]", "facet.field",
538: "trait_s", "facet.mincount", "0", "facet.offset", "0",
539: "facet.limit", "3"),
540: "*[count(//lst[@name='trait_s']/int)=3]",
541: "//lst[@name='trait_s']/int[@name='Tool'][.='2']",
542: "//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']",
543: "//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']");
544:
545: }
546:
547: public void testFacetMultiValued() {
548: doFacets("t_s");
549: doFacets("t_s", "facet.enum.cache.minDf", "2");
550: doFacets("t_s", "facet.enum.cache.minDf", "100");
551: }
552:
553: public void testFacetSingleValued() {
554: doFacets("t_s1");
555: }
556:
557: public void doFacets(String f, String... params) {
558: String pre = "//lst[@name='" + f + "']";
559: String notc = "id:[* TO *] -" + f + ":C";
560:
561: assertU(adoc("id", "1", f, "A"));
562: assertU(adoc("id", "2", f, "B"));
563: assertU(adoc("id", "3", f, "C"));
564: assertU(adoc("id", "4", f, "C"));
565: assertU(adoc("id", "5", f, "D"));
566: assertU(adoc("id", "6", f, "E"));
567: assertU(adoc("id", "7", f, "E"));
568: assertU(adoc("id", "8", f, "E"));
569: assertU(adoc("id", "9", f, "F"));
570: assertU(adoc("id", "10", f, "G"));
571: assertU(adoc("id", "11", f, "G"));
572: assertU(adoc("id", "12", f, "G"));
573: assertU(adoc("id", "13", f, "G"));
574: assertU(adoc("id", "14", f, "G"));
575: assertU(commit());
576:
577: assertQ("check counts for unlimited facet", req(params, "q",
578: "id:[* TO *]", "facet", "true", "facet.field", f),
579: "*[count(//lst[@name='facet_fields']/lst/int)=7]"
580:
581: , pre + "/int[@name='G'][.='5']", pre
582: + "/int[@name='E'][.='3']", pre
583: + "/int[@name='C'][.='2']"
584:
585: , pre + "/int[@name='A'][.='1']", pre
586: + "/int[@name='B'][.='1']", pre
587: + "/int[@name='D'][.='1']", pre
588: + "/int[@name='F'][.='1']");
589:
590: assertQ("check counts for facet with generous limit", req(
591: params, "q", "id:[* TO *]", "facet", "true",
592: "facet.limit", "100", "facet.field", f),
593: "*[count(//lst[@name='facet_fields']/lst/int)=7]"
594:
595: , pre + "/int[1][@name='G'][.='5']", pre
596: + "/int[2][@name='E'][.='3']", pre
597: + "/int[3][@name='C'][.='2']"
598:
599: , pre + "/int[@name='A'][.='1']", pre
600: + "/int[@name='B'][.='1']", pre
601: + "/int[@name='D'][.='1']", pre
602: + "/int[@name='F'][.='1']");
603:
604: assertQ("check counts for limited facet", req(params, "q",
605: "id:[* TO *]", "facet", "true", "facet.limit", "2",
606: "facet.field", f),
607: "*[count(//lst[@name='facet_fields']/lst/int)=2]"
608:
609: , pre + "/int[1][@name='G'][.='5']", pre
610: + "/int[2][@name='E'][.='3']");
611:
612: assertQ("check offset", req(params, "q", "id:[* TO *]",
613: "facet", "true", "facet.offset", "1", "facet.limit",
614: "1", "facet.field", f),
615: "*[count(//lst[@name='facet_fields']/lst/int)=1]"
616:
617: , pre + "/int[1][@name='E'][.='3']");
618:
619: assertQ(
620: "test sorted facet paging with zero (don't count in limit)",
621: req(params, "q", "id:[* TO *]", "fq", notc, "facet",
622: "true", "facet.field", f, "facet.mincount",
623: "1", "facet.offset", "0", "facet.limit", "6"),
624: "*[count(//lst[@name='facet_fields']/lst/int)=6]", pre
625: + "/int[1][@name='G'][.='5']", pre
626: + "/int[2][@name='E'][.='3']", pre
627: + "/int[3][@name='A'][.='1']", pre
628: + "/int[4][@name='B'][.='1']", pre
629: + "/int[5][@name='D'][.='1']", pre
630: + "/int[6][@name='F'][.='1']");
631:
632: assertQ(
633: "test sorted facet paging with zero (test offset correctness)",
634: req(params, "q", "id:[* TO *]", "fq", notc, "facet",
635: "true", "facet.field", f, "facet.mincount",
636: "1", "facet.offset", "3", "facet.limit", "2",
637: "facet.sort", "true"),
638: "*[count(//lst[@name='facet_fields']/lst/int)=2]", pre
639: + "/int[1][@name='B'][.='1']", pre
640: + "/int[2][@name='D'][.='1']");
641:
642: assertQ("test facet unsorted paging", req(params, "q",
643: "id:[* TO *]", "fq", notc, "facet", "true",
644: "facet.field", f, "facet.mincount", "1",
645: "facet.offset", "0", "facet.limit", "6", "facet.sort",
646: "false"),
647: "*[count(//lst[@name='facet_fields']/lst/int)=6]", pre
648: + "/int[1][@name='A'][.='1']", pre
649: + "/int[2][@name='B'][.='1']", pre
650: + "/int[3][@name='D'][.='1']", pre
651: + "/int[4][@name='E'][.='3']", pre
652: + "/int[5][@name='F'][.='1']", pre
653: + "/int[6][@name='G'][.='5']");
654:
655: assertQ("test facet unsorted paging", req(params, "q",
656: "id:[* TO *]", "fq", notc, "facet", "true",
657: "facet.field", f, "facet.mincount", "1",
658: "facet.offset", "3", "facet.limit", "2", "facet.sort",
659: "false"),
660: "*[count(//lst[@name='facet_fields']/lst/int)=2]", pre
661: + "/int[1][@name='E'][.='3']", pre
662: + "/int[2][@name='F'][.='1']");
663:
664: assertQ("test facet unsorted paging, mincount=2", req(params,
665: "q", "id:[* TO *]", "fq", notc, "facet", "true",
666: "facet.field", f, "facet.mincount", "2",
667: "facet.offset", "1", "facet.limit", "2", "facet.sort",
668: "false"),
669: "*[count(//lst[@name='facet_fields']/lst/int)=1]", pre
670: + "/int[1][@name='G'][.='5']");
671: }
672:
673: public void testFacetPrefixMultiValued() {
674: doFacetPrefix("t_s");
675: doFacetPrefix("t_s", "facet.enum.cache.minDf", "3");
676: doFacetPrefix("t_s", "facet.enum.cache.minDf", "100");
677: }
678:
679: public void testFacetPrefixSingleValued() {
680: doFacetPrefix("t_s1");
681: }
682:
683: public void doFacetPrefix(String f, String... params) {
684: String indent = "on";
685: String pre = "//lst[@name='" + f + "']";
686: String notc = "id:[* TO *] -" + f + ":C";
687:
688: assertU(adoc("id", "1", f, "AAA"));
689: assertU(adoc("id", "2", f, "B"));
690: assertU(adoc("id", "3", f, "BB"));
691: assertU(adoc("id", "4", f, "BB"));
692: assertU(adoc("id", "5", f, "BBB"));
693: assertU(adoc("id", "6", f, "BBB"));
694: assertU(adoc("id", "7", f, "BBB"));
695: assertU(adoc("id", "8", f, "CC"));
696: assertU(adoc("id", "9", f, "CC"));
697: assertU(adoc("id", "10", f, "CCC"));
698: assertU(adoc("id", "11", f, "CCC"));
699: assertU(adoc("id", "12", f, "CCC"));
700: assertU(commit());
701:
702: assertQ("test facet.prefix middle, exact match first term",
703: req(params, "q", "id:[* TO *]", "indent", indent,
704: "facet", "true", "facet.field", f,
705: "facet.mincount", "0", "facet.offset", "0",
706: "facet.limit", "100", "facet.sort", "true",
707: "facet.prefix", "B"),
708: "*[count(//lst[@name='facet_fields']/lst/int)=3]", pre
709: + "/int[1][@name='BBB'][.='3']", pre
710: + "/int[2][@name='BB'][.='2']", pre
711: + "/int[3][@name='B'][.='1']");
712:
713: assertQ(
714: "test facet.prefix middle, exact match first term, unsorted",
715: req(params, "q", "id:[* TO *]", "indent", indent,
716: "facet", "true", "facet.field", f,
717: "facet.mincount", "0", "facet.offset", "0",
718: "facet.limit", "100", "facet.sort", "false",
719: "facet.prefix", "B"),
720: "*[count(//lst[@name='facet_fields']/lst/int)=3]", pre
721: + "/int[1][@name='B'][.='1']", pre
722: + "/int[2][@name='BB'][.='2']", pre
723: + "/int[3][@name='BBB'][.='3']");
724:
725: assertQ(
726: "test facet.prefix middle, exact match first term, unsorted",
727: req(params, "q", "id:[* TO *]", "indent", indent,
728: "facet", "true", "facet.field", f,
729: "facet.mincount", "0", "facet.offset", "0",
730: "facet.limit", "100", "facet.sort", "false",
731: "facet.prefix", "B"),
732: "*[count(//lst[@name='facet_fields']/lst/int)=3]", pre
733: + "/int[1][@name='B'][.='1']", pre
734: + "/int[2][@name='BB'][.='2']", pre
735: + "/int[3][@name='BBB'][.='3']");
736:
737: assertQ("test facet.prefix middle, paging", req(params, "q",
738: "id:[* TO *]", "indent", indent, "facet", "true",
739: "facet.field", f, "facet.mincount", "0",
740: "facet.offset", "1", "facet.limit", "100",
741: "facet.sort", "true", "facet.prefix", "B"),
742: "*[count(//lst[@name='facet_fields']/lst/int)=2]", pre
743: + "/int[1][@name='BB'][.='2']", pre
744: + "/int[2][@name='B'][.='1']");
745:
746: assertQ("test facet.prefix middle, paging", req(params, "q",
747: "id:[* TO *]", "indent", indent, "facet", "true",
748: "facet.field", f, "facet.mincount", "0",
749: "facet.offset", "1", "facet.limit", "1", "facet.sort",
750: "true", "facet.prefix", "B"),
751: "*[count(//lst[@name='facet_fields']/lst/int)=1]", pre
752: + "/int[1][@name='BB'][.='2']");
753:
754: assertQ("test facet.prefix middle, paging", req(params, "q",
755: "id:[* TO *]", "indent", indent, "facet", "true",
756: "facet.field", f, "facet.mincount", "0",
757: "facet.offset", "1", "facet.limit", "1", "facet.sort",
758: "true", "facet.prefix", "B"),
759: "*[count(//lst[@name='facet_fields']/lst/int)=1]", pre
760: + "/int[1][@name='BB'][.='2']");
761:
762: assertQ("test facet.prefix end, not exact match", req(params,
763: "q", "id:[* TO *]", "indent", indent, "facet", "true",
764: "facet.field", f, "facet.mincount", "0",
765: "facet.offset", "0", "facet.limit", "100",
766: "facet.sort", "true", "facet.prefix", "C"),
767: "*[count(//lst[@name='facet_fields']/lst/int)=2]", pre
768: + "/int[1][@name='CCC'][.='3']", pre
769: + "/int[2][@name='CC'][.='2']");
770:
771: assertQ("test facet.prefix end, exact match", req(params, "q",
772: "id:[* TO *]", "indent", indent, "facet", "true",
773: "facet.field", f, "facet.mincount", "0",
774: "facet.offset", "0", "facet.limit", "100",
775: "facet.sort", "true", "facet.prefix", "CC"),
776: "*[count(//lst[@name='facet_fields']/lst/int)=2]", pre
777: + "/int[1][@name='CCC'][.='3']", pre
778: + "/int[2][@name='CC'][.='2']");
779:
780: assertQ("test facet.prefix past end", req(params, "q",
781: "id:[* TO *]", "indent", indent, "facet", "true",
782: "facet.field", f, "facet.mincount", "0",
783: "facet.offset", "0", "facet.limit", "100",
784: "facet.sort", "true", "facet.prefix", "X"),
785: "*[count(//lst[@name='facet_fields']/lst/int)=0]");
786:
787: assertQ("test facet.prefix past end", req(params, "q",
788: "id:[* TO *]", "indent", indent, "facet", "true",
789: "facet.field", f, "facet.mincount", "0",
790: "facet.offset", "1", "facet.limit", "-1", "facet.sort",
791: "true", "facet.prefix", "X"),
792: "*[count(//lst[@name='facet_fields']/lst/int)=0]");
793:
794: assertQ("test facet.prefix at start, exact match", req(params,
795: "q", "id:[* TO *]", "indent", indent, "facet", "true",
796: "facet.field", f, "facet.mincount", "0",
797: "facet.offset", "0", "facet.limit", "100",
798: "facet.sort", "true", "facet.prefix", "AAA"),
799: "*[count(//lst[@name='facet_fields']/lst/int)=1]", pre
800: + "/int[1][@name='AAA'][.='1']");
801: assertQ("test facet.prefix at Start, not exact match", req(
802: params, "q", "id:[* TO *]", "indent", indent, "facet",
803: "true", "facet.field", f, "facet.mincount", "0",
804: "facet.offset", "0", "facet.limit", "100",
805: "facet.sort", "true", "facet.prefix", "AA"),
806: "*[count(//lst[@name='facet_fields']/lst/int)=1]", pre
807: + "/int[1][@name='AAA'][.='1']");
808: assertQ("test facet.prefix at Start, not exact match", req(
809: params, "q", "id:[* TO *]", "indent", indent, "facet",
810: "true", "facet.field", f, "facet.mincount", "0",
811: "facet.offset", "0", "facet.limit", "100",
812: "facet.sort", "true", "facet.prefix", "AA"),
813: "*[count(//lst[@name='facet_fields']/lst/int)=1]", pre
814: + "/int[1][@name='AAA'][.='1']");
815: assertQ("test facet.prefix before start", req(params, "q",
816: "id:[* TO *]", "indent", indent, "facet", "true",
817: "facet.field", f, "facet.mincount", "0",
818: "facet.offset", "0", "facet.limit", "100",
819: "facet.sort", "true", "facet.prefix", "999"),
820: "*[count(//lst[@name='facet_fields']/lst/int)=0]");
821:
822: assertQ("test facet.prefix before start", req(params, "q",
823: "id:[* TO *]", "indent", indent, "facet", "true",
824: "facet.field", f, "facet.mincount", "0",
825: "facet.offset", "2", "facet.limit", "100",
826: "facet.sort", "true", "facet.prefix", "999"),
827: "*[count(//lst[@name='facet_fields']/lst/int)=0]");
828:
829: }
830:
831: private String mkstr(int len) {
832: StringBuilder sb = new StringBuilder(len);
833: for (int i = 0; i < len; i++) {
834: sb.append((char) (65 + i % 26));
835: }
836: return new String(sb);
837: }
838:
839: public void testCompressableFieldType() {
840:
841: IndexSchema ischema = new IndexSchema(getSchemaFile());
842: SchemaField f; // Solr field type
843: Field luf; // Lucene field
844:
845: f = ischema.getField("test_hlt");
846: luf = f.createField("test", 0f);
847: assertFalse(luf.isCompressed());
848: assertTrue(luf.isStored());
849:
850: f = ischema.getField("test_hlt");
851: luf = f.createField(mkstr(345), 0f);
852: assertTrue(luf.isCompressed());
853: assertTrue(luf.isStored());
854:
855: f = ischema.getField("test_hlt_off");
856: luf = f.createField(mkstr(400), 0f);
857: assertFalse(luf.isCompressed());
858: assertTrue(luf.isStored());
859:
860: }
861:
862: public void testNotLazyField() throws IOException {
863: for (int i = 0; i < 10; i++) {
864: assertU(adoc("id", new Integer(i).toString(), "title",
865: "keyword", "test_hlt", mkstr(20000)));
866: }
867: assertU(commit());
868: SolrCore core = h.getCore();
869:
870: SolrQueryRequest req = req("q", "title:keyword", "fl",
871: "id,title,test_hlt");
872: SolrQueryResponse rsp = new SolrQueryResponse();
873: core.execute(req, rsp);
874:
875: DocList dl = (DocList) rsp.getValues().get("response");
876: org.apache.lucene.document.Document d = req.getSearcher().doc(
877: dl.iterator().nextDoc());
878: // ensure field is not lazy
879: assertTrue(d.getFieldable("test_hlt") instanceof Field);
880: assertTrue(d.getFieldable("title") instanceof Field);
881: }
882:
883: public void testLazyField() throws IOException {
884: for (int i = 0; i < 10; i++) {
885: assertU(adoc("id", new Integer(i).toString(), "title",
886: "keyword", "test_hlt", mkstr(20000)));
887: }
888: assertU(commit());
889: SolrCore core = h.getCore();
890:
891: SolrQueryRequest req = req("q", "title:keyword", "fl",
892: "id,title");
893: SolrQueryResponse rsp = new SolrQueryResponse();
894: core.execute(req, rsp);
895:
896: DocList dl = (DocList) rsp.getValues().get("response");
897: DocIterator di = dl.iterator();
898: org.apache.lucene.document.Document d = req.getSearcher().doc(
899: di.nextDoc());
900: // ensure field is lazy
901: assertTrue(!(d.getFieldable("test_hlt") instanceof Field));
902: assertTrue(d.getFieldable("title") instanceof Field);
903: }
904:
905: /** @see org.apache.solr.util.DateMathParserTest */
906: public void testDateMath() {
907:
908: // testing everything from query level is hard because
909: // time marches on ... and there is no easy way to reach into the
910: // bowels of DateField and muck with the definition of "now"
911: // ...
912: // BUT: we can test that crazy combinations of "NOW" all work correctly,
913: // assuming the test doesn't take too long to run...
914:
915: assertU(adoc("id", "1", "bday", "1976-07-04T12:08:56.235Z"));
916: assertU(adoc("id", "2", "bday", "NOW"));
917: assertU(adoc("id", "3", "bday", "NOW/HOUR"));
918: assertU(adoc("id", "4", "bday", "NOW-30MINUTES"));
919: assertU(adoc("id", "5", "bday", "NOW+30MINUTES"));
920: assertU(adoc("id", "6", "bday", "NOW+2YEARS"));
921: assertU(commit());
922:
923: assertQ("check count for before now", req("q",
924: "bday:[* TO NOW]"), "*[count(//doc)=4]");
925:
926: assertQ("check count for after now",
927: req("q", "bday:[NOW TO *]"), "*[count(//doc)=2]");
928:
929: assertQ("check count for old stuff", req("q",
930: "bday:[* TO NOW-2YEARS]"), "*[count(//doc)=1]");
931:
932: assertQ("check count for future stuff", req("q",
933: "bday:[NOW+1MONTH TO *]"), "*[count(//doc)=1]");
934:
935: assertQ("check count for near stuff", req("q",
936: "bday:[NOW-1MONTH TO NOW+2HOURS]"), "*[count(//doc)=4]");
937:
938: }
939:
940: public void testPatternReplaceFilter() {
941:
942: assertU(adoc("id", "1", "patternreplacefilt",
943: "My fine-feathered friend!"));
944: assertU(adoc("id", "2", "patternreplacefilt",
945: " What's Up Doc?"));
946: assertU(commit());
947:
948: assertQ("don't find Up", req("q", "patternreplacefilt:Up"),
949: "*[count(//doc)=0]");
950:
951: assertQ("find doc", req("q",
952: "patternreplacefilt:__What_s_Up_Doc_"),
953: "*[count(//doc)=1]");
954:
955: assertQ("find birds", req("q",
956: "patternreplacefilt:My__fine_feathered_friend_"),
957: "*[count(//doc)=1]");
958: }
959:
960: // /** this doesn't work, but if it did, this is how we'd test it. */
961: // public void testOverwriteFalse() {
962:
963: // assertU(adoc("id", "overwrite", "val_s", "AAA"));
964: // assertU(commit());
965:
966: // assertU(add(doc("id", "overwrite", "val_s", "BBB")
967: // ,"allowDups", "false"
968: // ,"overwriteCommitted","false"
969: // ,"overwritePending","false"
970: // ));
971: // assertU(commit());
972: // assertQ(req("id:overwrite")
973: // ,"//*[@numFound='1']"
974: // ,"//str[.='AAA']"
975: // );
976: // }
977:
978: }
|