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));