1 package org.apache.lucene.index;
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 java.io.IOException;
21 import java.util.Arrays;
23 import org.apache.lucene.analysis.MockAnalyzer;
24 import org.apache.lucene.document.Document;
25 import org.apache.lucene.document.Field;
26 import org.apache.lucene.search.Collector;
27 import org.apache.lucene.search.DefaultSimilarity;
28 import org.apache.lucene.search.IndexSearcher;
29 import org.apache.lucene.search.Scorer;
30 import org.apache.lucene.search.Similarity;
31 import org.apache.lucene.search.TermQuery;
32 import org.apache.lucene.store.Directory;
33 import org.apache.lucene.util.LuceneTestCase;
36 * Tests changing of field norms with a custom similarity and with fake norms.
38 public class TestFieldNormModifier extends LuceneTestCase {
39 public static int NUM_DOCS = 5;
41 public Directory store;
43 /** inverts the normal notion of lengthNorm */
44 public static Similarity s = new DefaultSimilarity() {
46 public float computeNorm(String fieldName, FieldInvertState state) {
47 return state.getBoost() * (discountOverlaps ? state.getLength() - state.getNumOverlap() : state.getLength());
52 public void setUp() throws Exception {
54 store = newDirectory();
55 IndexWriter writer = new IndexWriter(store, newIndexWriterConfig(
56 TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
58 for (int i = 0; i < NUM_DOCS; i++) {
59 Document d = new Document();
60 d.add(newField("field", "word", Field.Store.YES, Field.Index.ANALYZED));
61 d.add(newField("nonorm", "word", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
62 d.add(newField("untokfield", "20061212 20071212", Field.Store.YES, Field.Index.ANALYZED));
64 for (int j = 1; j <= i; j++) {
65 d.add(newField("field", "crap", Field.Store.YES, Field.Index.ANALYZED));
66 d.add(newField("nonorm", "more words", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
68 writer.addDocument(d);
74 public void tearDown() throws Exception {
79 public void testMissingField() throws Exception {
80 FieldNormModifier fnm = new FieldNormModifier(store, s);
82 fnm.reSetNorms("nobodyherebutuschickens");
83 } catch (IllegalStateException e) {
88 public void testFieldWithNoNorm() throws Exception {
90 IndexReader r = IndexReader.open(store, false);
91 byte[] norms = r.norms("nonorm");
93 // sanity check, norms should all be 1
94 assertTrue("Whoops we have norms?", !r.hasNorms("nonorm"));
99 FieldNormModifier fnm = new FieldNormModifier(store, s);
101 fnm.reSetNorms("nonorm");
102 } catch (IllegalStateException e) {
106 // nothing should have changed
107 r = IndexReader.open(store, false);
109 norms = r.norms("nonorm");
110 assertTrue("Whoops we have norms?", !r.hasNorms("nonorm"));
117 public void testGoodCases() throws Exception {
119 IndexReader reader = IndexReader.open(store);
120 IndexSearcher searcher = new IndexSearcher(reader);
121 final float[] scores = new float[NUM_DOCS];
122 float lastScore = 0.0f;
124 // default similarity should put docs with shorter length first
125 searcher.search(new TermQuery(new Term("field", "word")), new Collector() {
126 private int docBase = 0;
127 private Scorer scorer;
130 public final void collect(int doc) throws IOException {
131 scores[doc + docBase] = scorer.score();
134 public void setNextReader(IndexReader reader, int docBase) {
135 this.docBase = docBase;
138 public void setScorer(Scorer scorer) throws IOException {
139 this.scorer = scorer;
142 public boolean acceptsDocsOutOfOrder() {
149 lastScore = Float.MAX_VALUE;
150 for (int i = 0; i < NUM_DOCS; i++) {
151 String msg = "i=" + i + ", " + scores[i] + " <= " + lastScore;
152 assertTrue(msg, scores[i] <= lastScore);
153 //System.out.println(msg);
154 lastScore = scores[i];
157 FieldNormModifier fnm = new FieldNormModifier(store, s);
158 fnm.reSetNorms("field");
160 // new norm (with default similarity) should put longer docs first
161 reader = IndexReader.open(store);
162 searcher = new IndexSearcher(reader);
163 searcher.search(new TermQuery(new Term("field", "word")), new Collector() {
164 private int docBase = 0;
165 private Scorer scorer;
167 public final void collect(int doc) throws IOException {
168 scores[doc + docBase] = scorer.score();
171 public void setNextReader(IndexReader reader, int docBase) {
172 this.docBase = docBase;
175 public void setScorer(Scorer scorer) throws IOException {
176 this.scorer = scorer;
179 public boolean acceptsDocsOutOfOrder() {
187 for (int i = 0; i < NUM_DOCS; i++) {
188 String msg = "i=" + i + ", " + scores[i] + " >= " + lastScore;
189 assertTrue(msg, scores[i] >= lastScore);
190 //System.out.println(msg);
191 lastScore = scores[i];
195 public void testNormKiller() throws IOException {
197 IndexReader r = IndexReader.open(store, false);
198 byte[] oldNorms = r.norms("untokfield");
201 FieldNormModifier fnm = new FieldNormModifier(store, s);
202 fnm.reSetNorms("untokfield");
204 r = IndexReader.open(store, false);
205 byte[] newNorms = r.norms("untokfield");
207 assertFalse(Arrays.equals(oldNorms, newNorms));
210 // verify that we still get documents in the same order as originally
211 IndexReader reader = IndexReader.open(store);
212 IndexSearcher searcher = new IndexSearcher(reader);
213 final float[] scores = new float[NUM_DOCS];
214 float lastScore = 0.0f;
216 // default similarity should return the same score for all documents for this query
217 searcher.search(new TermQuery(new Term("untokfield", "20061212")), new Collector() {
218 private int docBase = 0;
219 private Scorer scorer;
221 public final void collect(int doc) throws IOException {
222 scores[doc + docBase] = scorer.score();
225 public void setNextReader(IndexReader reader, int docBase) {
226 this.docBase = docBase;
229 public void setScorer(Scorer scorer) throws IOException {
230 this.scorer = scorer;
233 public boolean acceptsDocsOutOfOrder() {
240 lastScore = scores[0];
241 for (int i = 0; i < NUM_DOCS; i++) {
242 String msg = "i=" + i + ", " + scores[i] + " == " + lastScore;
243 assertTrue(msg, scores[i] == lastScore);
244 //System.out.println(msg);
245 lastScore = scores[i];