package org.apache.lucene.search;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.store.Directory;
import java.io.IOException;
/**
* Tests {@link MultiSearcher} ranking, i.e. makes sure this bug is fixed:
* http://issues.apache.org/bugzilla/show_bug.cgi?id=31841
*
*/
public class TestMultiSearcherRanking extends LuceneTestCase {
private final String FIELD_NAME = "body";
private Searcher multiSearcher;
private Searcher singleSearcher;
public void testOneTermQuery() throws IOException, ParseException {
checkQuery("three");
}
public void testTwoTermQuery() throws IOException, ParseException {
checkQuery("three foo");
}
public void testPrefixQuery() throws IOException, ParseException {
checkQuery("multi*");
}
public void testFuzzyQuery() throws IOException, ParseException {
checkQuery("multiThree~");
}
public void testRangeQuery() throws IOException, ParseException {
checkQuery("{multiA TO multiP}");
}
public void testMultiPhraseQuery() throws IOException, ParseException {
checkQuery("\"blueberry pi*\"");
}
public void testNoMatchQuery() throws IOException, ParseException {
checkQuery("+three +nomatch");
}
/*
public void testTermRepeatedQuery() throws IOException, ParseException {
// TODO: this corner case yields different results.
checkQuery("multi* multi* foo");
}
*/
/**
* checks if a query yields the same result when executed on
* a single IndexSearcher containing all documents and on a
* MultiSearcher aggregating sub-searchers
* @param queryStr the query to check.
* @throws IOException
* @throws ParseException
*/
private void checkQuery(String queryStr) throws IOException, ParseException {
// check result hit ranking
if(VERBOSE) System.out.println("Query: " + queryStr);
QueryParser queryParser = new QueryParser(TEST_VERSION_CURRENT, FIELD_NAME, new StandardAnalyzer(TEST_VERSION_CURRENT));
Query query = queryParser.parse(queryStr);
ScoreDoc[] multiSearcherHits = multiSearcher.search(query, null, 1000).scoreDocs;
ScoreDoc[] singleSearcherHits = singleSearcher.search(query, null, 1000).scoreDocs;
assertEquals(multiSearcherHits.length, singleSearcherHits.length);
for (int i = 0; i < multiSearcherHits.length; i++) {
Document docMulti = multiSearcher.doc(multiSearcherHits[i].doc);
Document docSingle = singleSearcher.doc(singleSearcherHits[i].doc);
if(VERBOSE) System.out.println("Multi: " + docMulti.get(FIELD_NAME) + " score="
+ multiSearcherHits[i].score);
if(VERBOSE) System.out.println("Single: " + docSingle.get(FIELD_NAME) + " score="
+ singleSearcherHits[i].score);
assertEquals(multiSearcherHits[i].score, singleSearcherHits[i].score,
0.001f);
assertEquals(docMulti.get(FIELD_NAME), docSingle.get(FIELD_NAME));
}
if(VERBOSE) System.out.println();
}
/**
* initializes multiSearcher and singleSearcher with the same document set
*/
@Override
public void setUp() throws Exception {
super.setUp();
// create MultiSearcher from two seperate searchers
d1 = newDirectory();
IndexWriter iw1 = new IndexWriter(d1, newIndexWriterConfig(TEST_VERSION_CURRENT, new StandardAnalyzer(TEST_VERSION_CURRENT)).setMergePolicy(newLogMergePolicy()));
addCollection1(iw1);
iw1.close();
d2 = newDirectory();
IndexWriter iw2 = new IndexWriter(d2, newIndexWriterConfig(TEST_VERSION_CURRENT, new StandardAnalyzer(TEST_VERSION_CURRENT)).setMergePolicy(newLogMergePolicy()));
addCollection2(iw2);
iw2.close();
Searchable[] s = new Searchable[2];
s[0] = new IndexSearcher(d1, true);
s[1] = new IndexSearcher(d2, true);
multiSearcher = new MultiSearcher(s);
// create IndexSearcher which contains all documents
d = newDirectory();
IndexWriter iw = new IndexWriter(d, newIndexWriterConfig(TEST_VERSION_CURRENT, new StandardAnalyzer(TEST_VERSION_CURRENT)).setMergePolicy(newLogMergePolicy()));
addCollection1(iw);
addCollection2(iw);
iw.close();
singleSearcher = new IndexSearcher(d, true);
}
Directory d1, d2, d;
@Override
public void tearDown() throws Exception {
multiSearcher.close();
singleSearcher.close();
d1.close();
d2.close();
d.close();
super.tearDown();
}
private void addCollection1(IndexWriter iw) throws IOException {
add("one blah three", iw);
add("one foo three multiOne", iw);
add("one foobar three multiThree", iw);
add("blueberry pie", iw);
add("blueberry strudel", iw);
add("blueberry pizza", iw);
}
private void addCollection2(IndexWriter iw) throws IOException {
add("two blah three", iw);
add("two foo xxx multiTwo", iw);
add("two foobar xxx multiThreee", iw);
add("blueberry chewing gum", iw);
add("bluebird pizza", iw);
add("bluebird foobar pizza", iw);
add("piccadilly circus", iw);
}
private void add(String value, IndexWriter iw) throws IOException {
Document d = new Document();
d.add(newField(FIELD_NAME, value, Field.Store.YES, Field.Index.ANALYZED));
iw.addDocument(d);
}
}