1 package org.apache.lucene.search.function;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 import org.apache.lucene.index.CorruptIndexException;
21 import org.apache.lucene.index.IndexReader;
22 import org.apache.lucene.search.*;
23 import org.junit.BeforeClass;
24 import org.junit.Test;
27 * Test search based on OrdFieldSource and ReverseOrdFieldSource.
29 * Tests here create an index with a few documents, each having
30 * an indexed "id" field.
31 * The ord values of this field are later used for scoring.
33 * The order tests use Hits to verify that docs are ordered as expected.
35 * The exact score tests use TopDocs top to verify the exact score.
37 public class TestOrdValues extends FunctionTestSetup {
40 public static void beforeClass() throws Exception {
48 public void testOrdFieldRank() throws CorruptIndexException, Exception {
49 doTestRank(ID_FIELD, true);
53 * Test ReverseOrdFieldSource
56 public void testReverseOrdFieldRank() throws CorruptIndexException, Exception {
57 doTestRank(ID_FIELD, false);
60 // Test that queries based on reverse/ordFieldScore scores correctly
61 private void doTestRank(String field, boolean inOrder) throws CorruptIndexException, Exception {
62 IndexSearcher s = new IndexSearcher(dir, true);
65 vs = new OrdFieldSource(field);
67 vs = new ReverseOrdFieldSource(field);
70 Query q = new ValueSourceQuery(vs);
72 QueryUtils.check(random, q, s);
73 ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
74 assertEquals("All docs should be matched!", N_DOCS, h.length);
75 String prevID = inOrder
76 ? "IE" // greater than all ids of docs in this test ("ID0001", etc.)
77 : "IC"; // smaller than all ids of docs in this test ("ID0001", etc.)
79 for (int i = 0; i < h.length; i++) {
80 String resID = s.doc(h[i].doc).get(ID_FIELD);
81 log(i + ". score=" + h[i].score + " - " + resID);
82 log(s.explain(q, h[i].doc));
84 assertTrue("res id " + resID + " should be < prev res id " + prevID, resID.compareTo(prevID) < 0);
86 assertTrue("res id " + resID + " should be > prev res id " + prevID, resID.compareTo(prevID) > 0);
94 * Test exact score for OrdFieldSource
97 public void testOrdFieldExactScore() throws CorruptIndexException, Exception {
98 doTestExactScore(ID_FIELD, true);
102 * Test exact score for ReverseOrdFieldSource
105 public void testReverseOrdFieldExactScore() throws CorruptIndexException, Exception {
106 doTestExactScore(ID_FIELD, false);
110 // Test that queries based on reverse/ordFieldScore returns docs with expected score.
111 private void doTestExactScore(String field, boolean inOrder) throws CorruptIndexException, Exception {
112 IndexSearcher s = new IndexSearcher(dir, true);
115 vs = new OrdFieldSource(field);
117 vs = new ReverseOrdFieldSource(field);
119 Query q = new ValueSourceQuery(vs);
120 TopDocs td = s.search(q, null, 1000);
121 assertEquals("All docs should be matched!", N_DOCS, td.totalHits);
122 ScoreDoc sd[] = td.scoreDocs;
123 for (int i = 0; i < sd.length; i++) {
124 float score = sd[i].score;
125 String id = s.getIndexReader().document(sd[i].doc).get(ID_FIELD);
126 log("-------- " + i + ". Explain doc " + id);
127 log(s.explain(q, sd[i].doc));
128 float expectedScore = N_DOCS - i;
129 assertEquals("score of result " + i + " shuould be " + expectedScore + " != " + score, expectedScore, score, TEST_SCORE_TOLERANCE_DELTA);
130 String expectedId = inOrder
131 ? id2String(N_DOCS - i) // in-order ==> larger values first
132 : id2String(i + 1); // reverse ==> smaller values first
133 assertTrue("id of result " + i + " shuould be " + expectedId + " != " + score, expectedId.equals(id));
139 * Test caching OrdFieldSource
142 public void testCachingOrd() throws CorruptIndexException, Exception {
143 doTestCaching(ID_FIELD, true);
147 * Test caching for ReverseOrdFieldSource
150 public void testCachingReverseOrd() throws CorruptIndexException, Exception {
151 doTestCaching(ID_FIELD, false);
154 // Test that values loaded for FieldScoreQuery are cached properly and consumes the proper RAM resources.
155 private void doTestCaching(String field, boolean inOrder) throws CorruptIndexException, Exception {
156 IndexSearcher s = new IndexSearcher(dir, true);
157 Object innerArray = null;
159 boolean warned = false; // print warning once
161 for (int i = 0; i < 10; i++) {
164 vs = new OrdFieldSource(field);
166 vs = new ReverseOrdFieldSource(field);
168 ValueSourceQuery q = new ValueSourceQuery(vs);
169 ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
171 assertEquals("All docs should be matched!", N_DOCS, h.length);
172 IndexReader[] readers = s.getIndexReader().getSequentialSubReaders();
174 for (IndexReader reader : readers) {
176 innerArray = q.valSrc.getValues(reader).getInnerArray();
178 log(i + ". compare: " + innerArray + " to " + q.valSrc.getValues(reader).getInnerArray());
179 assertSame("field values should be cached and reused!", innerArray, q.valSrc.getValues(reader).getInnerArray());
182 } catch (UnsupportedOperationException e) {
184 System.err.println("WARNING: " + testName() + " cannot fully test values of " + q);
194 // verify that different values are loaded for a different field
195 String field2 = INT_FIELD;
196 assertFalse(field.equals(field2)); // otherwise this test is meaningless.
198 vs = new OrdFieldSource(field2);
200 vs = new ReverseOrdFieldSource(field2);
202 q = new ValueSourceQuery(vs);
203 h = s.search(q, null, 1000).scoreDocs;
204 assertEquals("All docs should be matched!", N_DOCS, h.length);
205 IndexReader[] readers = s.getIndexReader().getSequentialSubReaders();
207 for (IndexReader reader : readers) {
209 log("compare (should differ): " + innerArray + " to "
210 + q.valSrc.getValues(reader).getInnerArray());
212 "different values shuold be loaded for a different field!",
213 innerArray, q.valSrc.getValues(reader).getInnerArray());
214 } catch (UnsupportedOperationException e) {
216 System.err.println("WARNING: " + testName()
217 + " cannot fully test values of " + q);
223 // verify new values are reloaded (not reused) for a new reader
224 s = new IndexSearcher(dir, true);
226 vs = new OrdFieldSource(field);
228 vs = new ReverseOrdFieldSource(field);
230 q = new ValueSourceQuery(vs);
231 h = s.search(q, null, 1000).scoreDocs;
232 assertEquals("All docs should be matched!", N_DOCS, h.length);
233 readers = s.getIndexReader().getSequentialSubReaders();
235 for (IndexReader reader : readers) {
237 log("compare (should differ): " + innerArray + " to "
238 + q.valSrc.getValues(reader).getInnerArray());
240 "cached field values should not be reused if reader as changed!",
241 innerArray, q.valSrc.getValues(reader).getInnerArray());
242 } catch (UnsupportedOperationException e) {
244 System.err.println("WARNING: " + testName()
245 + " cannot fully test values of " + q);
253 private String testName() {
254 return getClass().getName() + "." + getName();
258 public void testEqualsNull() throws Exception {
259 OrdFieldSource ofs = new OrdFieldSource("f");
260 assertFalse(ofs.equals(null));
262 ReverseOrdFieldSource rofs = new ReverseOrdFieldSource("f");
263 assertFalse(rofs.equals(null));