001: package org.apache.lucene.search;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import org.apache.lucene.analysis.WhitespaceAnalyzer;
021: import org.apache.lucene.document.Document;
022: import org.apache.lucene.document.Field;
023: import org.apache.lucene.index.IndexReader;
024: import org.apache.lucene.index.IndexWriter;
025: import org.apache.lucene.index.Term;
026: import org.apache.lucene.store.Directory;
027: import org.apache.lucene.store.RAMDirectory;
028:
029: import java.io.IOException;
030:
031: import junit.framework.Assert;
032:
033: public class TestConstantScoreRangeQuery extends BaseTestRangeFilter {
034:
035: /** threshold for comparing floats */
036: public static final float SCORE_COMP_THRESH = 1e-6f;
037:
038: public TestConstantScoreRangeQuery(String name) {
039: super (name);
040: }
041:
042: public TestConstantScoreRangeQuery() {
043: super ();
044: }
045:
046: Directory small;
047:
048: void assertEquals(String m, float e, float a) {
049: assertEquals(m, e, a, SCORE_COMP_THRESH);
050: }
051:
052: static public void assertEquals(String m, int e, int a) {
053: Assert.assertEquals(m, e, a);
054: }
055:
056: public void setUp() throws Exception {
057: super .setUp();
058:
059: String[] data = new String[] { "A 1 2 3 4 5 6",
060: "Z 4 5 6", null, "B 2 4 5 6",
061: "Y 3 5 6", null, "C 3 6", "X 4 5 6" };
062:
063: small = new RAMDirectory();
064: IndexWriter writer = new IndexWriter(small,
065: new WhitespaceAnalyzer(), true);
066:
067: for (int i = 0; i < data.length; i++) {
068: Document doc = new Document();
069: doc.add(new Field("id", String.valueOf(i), Field.Store.YES,
070: Field.Index.UN_TOKENIZED));//Field.Keyword("id",String.valueOf(i)));
071: doc.add(new Field("all", "all", Field.Store.YES,
072: Field.Index.UN_TOKENIZED));//Field.Keyword("all","all"));
073: if (null != data[i]) {
074: doc.add(new Field("data", data[i], Field.Store.YES,
075: Field.Index.TOKENIZED));//Field.Text("data",data[i]));
076: }
077: writer.addDocument(doc);
078: }
079:
080: writer.optimize();
081: writer.close();
082: }
083:
084: /** macro for readability */
085: public static Query csrq(String f, String l, String h, boolean il,
086: boolean ih) {
087: return new ConstantScoreRangeQuery(f, l, h, il, ih);
088: }
089:
090: public void testBasics() throws IOException {
091: QueryUtils.check(csrq("data", "1", "6", T, T));
092: QueryUtils.check(csrq("data", "A", "Z", T, T));
093: QueryUtils.checkUnequal(csrq("data", "1", "6", T, T), csrq(
094: "data", "A", "Z", T, T));
095: }
096:
097: public void testEqualScores() throws IOException {
098: // NOTE: uses index build in *this* setUp
099:
100: IndexReader reader = IndexReader.open(small);
101: IndexSearcher search = new IndexSearcher(reader);
102:
103: Hits result;
104:
105: // some hits match more terms then others, score should be the same
106:
107: result = search.search(csrq("data", "1", "6", T, T));
108: int numHits = result.length();
109: assertEquals("wrong number of results", 6, numHits);
110: float score = result.score(0);
111: for (int i = 1; i < numHits; i++) {
112: assertEquals("score for " + i + " was not the same", score,
113: result.score(i));
114: }
115:
116: }
117:
118: public void testBoost() throws IOException {
119: // NOTE: uses index build in *this* setUp
120:
121: IndexReader reader = IndexReader.open(small);
122: IndexSearcher search = new IndexSearcher(reader);
123:
124: // test for correct application of query normalization
125: // must use a non score normalizing method for this.
126: Query q = csrq("data", "1", "6", T, T);
127: q.setBoost(100);
128: search.search(q, null, new HitCollector() {
129: public void collect(int doc, float score) {
130: assertEquals("score for doc " + doc
131: + " was not correct", 1.0f, score);
132: }
133: });
134:
135: //
136: // Ensure that boosting works to score one clause of a query higher
137: // than another.
138: //
139: Query q1 = csrq("data", "A", "A", T, T); // matches document #0
140: q1.setBoost(.1f);
141: Query q2 = csrq("data", "Z", "Z", T, T); // matches document #1
142: BooleanQuery bq = new BooleanQuery(true);
143: bq.add(q1, BooleanClause.Occur.SHOULD);
144: bq.add(q2, BooleanClause.Occur.SHOULD);
145:
146: Hits hits = search.search(bq);
147: assertEquals(1, hits.id(0));
148: assertEquals(0, hits.id(1));
149: assertTrue(hits.score(0) > hits.score(1));
150:
151: q1 = csrq("data", "A", "A", T, T); // matches document #0
152: q1.setBoost(10f);
153: q2 = csrq("data", "Z", "Z", T, T); // matches document #1
154: bq = new BooleanQuery(true);
155: bq.add(q1, BooleanClause.Occur.SHOULD);
156: bq.add(q2, BooleanClause.Occur.SHOULD);
157:
158: hits = search.search(bq);
159: assertEquals(0, hits.id(0));
160: assertEquals(1, hits.id(1));
161: assertTrue(hits.score(0) > hits.score(1));
162: }
163:
164: public void testBooleanOrderUnAffected() throws IOException {
165: // NOTE: uses index build in *this* setUp
166:
167: IndexReader reader = IndexReader.open(small);
168: IndexSearcher search = new IndexSearcher(reader);
169:
170: // first do a regular RangeQuery which uses term expansion so
171: // docs with more terms in range get higher scores
172:
173: Query rq = new RangeQuery(new Term("data", "1"), new Term(
174: "data", "4"), T);
175:
176: Hits expected = search.search(rq);
177: int numHits = expected.length();
178:
179: // now do a boolean where which also contains a
180: // ConstantScoreRangeQuery and make sure hte order is the same
181:
182: BooleanQuery q = new BooleanQuery();
183: q.add(rq, BooleanClause.Occur.MUST);//T, F);
184: q.add(csrq("data", "1", "6", T, T), BooleanClause.Occur.MUST);//T, F);
185:
186: Hits actual = search.search(q);
187:
188: assertEquals("wrong numebr of hits", numHits, actual.length());
189: for (int i = 0; i < numHits; i++) {
190: assertEquals("mismatch in docid for hit#" + i, expected
191: .id(i), actual.id(i));
192: }
193:
194: }
195:
196: public void testRangeQueryId() throws IOException {
197: // NOTE: uses index build in *super* setUp
198:
199: IndexReader reader = IndexReader.open(index);
200: IndexSearcher search = new IndexSearcher(reader);
201:
202: int medId = ((maxId - minId) / 2);
203:
204: String minIP = pad(minId);
205: String maxIP = pad(maxId);
206: String medIP = pad(medId);
207:
208: int numDocs = reader.numDocs();
209:
210: assertEquals("num of docs", numDocs, 1 + maxId - minId);
211:
212: Hits result;
213:
214: // test id, bounded on both ends
215:
216: result = search.search(csrq("id", minIP, maxIP, T, T));
217: assertEquals("find all", numDocs, result.length());
218:
219: result = search.search(csrq("id", minIP, maxIP, T, F));
220: assertEquals("all but last", numDocs - 1, result.length());
221:
222: result = search.search(csrq("id", minIP, maxIP, F, T));
223: assertEquals("all but first", numDocs - 1, result.length());
224:
225: result = search.search(csrq("id", minIP, maxIP, F, F));
226: assertEquals("all but ends", numDocs - 2, result.length());
227:
228: result = search.search(csrq("id", medIP, maxIP, T, T));
229: assertEquals("med and up", 1 + maxId - medId, result.length());
230:
231: result = search.search(csrq("id", minIP, medIP, T, T));
232: assertEquals("up to med", 1 + medId - minId, result.length());
233:
234: // unbounded id
235:
236: result = search.search(csrq("id", minIP, null, T, F));
237: assertEquals("min and up", numDocs, result.length());
238:
239: result = search.search(csrq("id", null, maxIP, F, T));
240: assertEquals("max and down", numDocs, result.length());
241:
242: result = search.search(csrq("id", minIP, null, F, F));
243: assertEquals("not min, but up", numDocs - 1, result.length());
244:
245: result = search.search(csrq("id", null, maxIP, F, F));
246: assertEquals("not max, but down", numDocs - 1, result.length());
247:
248: result = search.search(csrq("id", medIP, maxIP, T, F));
249: assertEquals("med and up, not max", maxId - medId, result
250: .length());
251:
252: result = search.search(csrq("id", minIP, medIP, F, T));
253: assertEquals("not min, up to med", medId - minId, result
254: .length());
255:
256: // very small sets
257:
258: result = search.search(csrq("id", minIP, minIP, F, F));
259: assertEquals("min,min,F,F", 0, result.length());
260: result = search.search(csrq("id", medIP, medIP, F, F));
261: assertEquals("med,med,F,F", 0, result.length());
262: result = search.search(csrq("id", maxIP, maxIP, F, F));
263: assertEquals("max,max,F,F", 0, result.length());
264:
265: result = search.search(csrq("id", minIP, minIP, T, T));
266: assertEquals("min,min,T,T", 1, result.length());
267: result = search.search(csrq("id", null, minIP, F, T));
268: assertEquals("nul,min,F,T", 1, result.length());
269:
270: result = search.search(csrq("id", maxIP, maxIP, T, T));
271: assertEquals("max,max,T,T", 1, result.length());
272: result = search.search(csrq("id", maxIP, null, T, F));
273: assertEquals("max,nul,T,T", 1, result.length());
274:
275: result = search.search(csrq("id", medIP, medIP, T, T));
276: assertEquals("med,med,T,T", 1, result.length());
277:
278: }
279:
280: public void testRangeQueryRand() throws IOException {
281: // NOTE: uses index build in *super* setUp
282:
283: IndexReader reader = IndexReader.open(index);
284: IndexSearcher search = new IndexSearcher(reader);
285:
286: String minRP = pad(minR);
287: String maxRP = pad(maxR);
288:
289: int numDocs = reader.numDocs();
290:
291: assertEquals("num of docs", numDocs, 1 + maxId - minId);
292:
293: Hits result;
294: Query q = new TermQuery(new Term("body", "body"));
295:
296: // test extremes, bounded on both ends
297:
298: result = search.search(csrq("rand", minRP, maxRP, T, T));
299: assertEquals("find all", numDocs, result.length());
300:
301: result = search.search(csrq("rand", minRP, maxRP, T, F));
302: assertEquals("all but biggest", numDocs - 1, result.length());
303:
304: result = search.search(csrq("rand", minRP, maxRP, F, T));
305: assertEquals("all but smallest", numDocs - 1, result.length());
306:
307: result = search.search(csrq("rand", minRP, maxRP, F, F));
308: assertEquals("all but extremes", numDocs - 2, result.length());
309:
310: // unbounded
311:
312: result = search.search(csrq("rand", minRP, null, T, F));
313: assertEquals("smallest and up", numDocs, result.length());
314:
315: result = search.search(csrq("rand", null, maxRP, F, T));
316: assertEquals("biggest and down", numDocs, result.length());
317:
318: result = search.search(csrq("rand", minRP, null, F, F));
319: assertEquals("not smallest, but up", numDocs - 1, result
320: .length());
321:
322: result = search.search(csrq("rand", null, maxRP, F, F));
323: assertEquals("not biggest, but down", numDocs - 1, result
324: .length());
325:
326: // very small sets
327:
328: result = search.search(csrq("rand", minRP, minRP, F, F));
329: assertEquals("min,min,F,F", 0, result.length());
330: result = search.search(csrq("rand", maxRP, maxRP, F, F));
331: assertEquals("max,max,F,F", 0, result.length());
332:
333: result = search.search(csrq("rand", minRP, minRP, T, T));
334: assertEquals("min,min,T,T", 1, result.length());
335: result = search.search(csrq("rand", null, minRP, F, T));
336: assertEquals("nul,min,F,T", 1, result.length());
337:
338: result = search.search(csrq("rand", maxRP, maxRP, T, T));
339: assertEquals("max,max,T,T", 1, result.length());
340: result = search.search(csrq("rand", maxRP, null, T, F));
341: assertEquals("max,nul,T,T", 1, result.length());
342:
343: }
344:
345: }
|