Add Hits.iterator and corresponding HitIterator and Hit classes. Contributed by Jeremy Rayner

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@164695 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Erik Hatcher 2005-04-26 00:21:53 +00:00
parent d650384d4b
commit ab83a46657
5 changed files with 266 additions and 0 deletions

View File

@ -91,6 +91,11 @@ New features
which lets the caller get the Lucene version information specified in
the Lucene Jar.
(Doug Cutting via Otis)
15. Added Hits.iterator() method and corresponding HitIterator and Hit objects.
This provides standard java.util.Iterator iteration over Hits.
Each call to the iterator's next() method returns a Hit object.
(Jeremy Rayner via Erik)
API Changes

View File

@ -0,0 +1,125 @@
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed 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.
*/
package org.apache.lucene.search;
import java.io.IOException;
import org.apache.lucene.document.Document;
/**
* a lazy future for a hit, useful for iterators over instances of Hits
*
* @author Jeremy Rayner
*/
public class Hit implements java.io.Serializable {
private float score;
private int id;
private Document doc = null;
private boolean resolved = false;
private Hits hits = null;
private int hitNumber;
/**
* Constructed from {@link HitIterator}
* @param hits Hits returned from a search
* @param hitNumber Hit index in Hits
*/
Hit(Hits hits, int hitNumber) {
this.hits = hits;
this.hitNumber = hitNumber;
}
/**
* Returns document for this hit.
*
* @see {@link Hits#doc(int)}
*/
public Document getDocument() throws IOException {
if (!resolved) fetchTheHit();
return doc;
}
/**
* Returns score for this hit.
*
* @see {@link Hits#score(int)}
*/
public float getScore() throws IOException {
if (!resolved) fetchTheHit();
return score;
}
/**
* Returns id for this hit.
*
* @see {@link Hits#id(int)}
*/
public int getId() throws IOException {
if (!resolved) fetchTheHit();
return id;
}
private void fetchTheHit() throws IOException {
doc = hits.doc(hitNumber);
score = hits.score(hitNumber);
id = hits.id(hitNumber);
resolved = true;
}
// provide some of the Document style interface (the simple stuff)
/**
* Returns the boost factor for this hit on any field of the underlying document.
*
* @see {@link Document#getBoost()}
*/
public float getBoost() throws IOException {
return getDocument().getBoost();
}
/**
* Returns the string value of the field with the given name if any exist in
* this document, or null. If multiple fields exist with this name, this
* method returns the first value added. If only binary fields with this name
* exist, returns null.
*
* @see {@link Document#get(String)}
*/
public String get(String name) throws IOException {
return getDocument().get(name);
}
/**
* Prints the fields of the underlying document for human consumption.
* <p/>
* If an IOException occurs whilst getting the document, returns null
*
* @see {@link Document#toString()}
*/
public String toString() {
try {
return getDocument().toString();
} catch (IOException e) {
return null;
}
}
}

View File

@ -0,0 +1,78 @@
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed 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.
*/
package org.apache.lucene.search;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* An iterator over {@link Hits} that provides lazy fetching of each document.
* {@link Hits#iterator()} returns an instance of this class. Calls to {@link #next()}
* return a {@link Hit} instance.
*
* @author Jeremy Rayner
*/
public class HitIterator implements Iterator {
private Hits hits;
private int hitNumber = 0;
/**
* Constructed from {@link Hits#iterator()}.
*/
HitIterator(Hits hits) {
this.hits = hits;
}
/**
* @return true if current hit is less than the total number of {@link Hits}.
*/
public boolean hasNext() {
return hitNumber < hits.length();
}
/**
* Returns a {@link Hit} instance representing the next hit in {@link Hits}.
*
* @return Next {@link Hit}.
*/
public Object next() {
try {
Object next = new Hit(hits, hitNumber);
hitNumber++;
return next;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
/**
* Unsupported operation.
*
* @throws UnsupportedOperationException
*/
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Returns the total number of hits.
*/
public int length() {
return hits.length();
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.search;
import java.io.IOException;
import java.util.Vector;
import java.util.Iterator;
import org.apache.lucene.document.Document;
@ -114,6 +115,13 @@ public final class Hits {
return hitDoc(n).id;
}
/**
* Returns an {@link Iterator} to navigate the Hits. Each item returned
* from {@link Iterator#next()} is a {@link Hit}.
*/
public Iterator iterator() {
return new HitIterator(this);
}
private final HitDoc hitDoc(int n) throws IOException {
if (n >= length) {

View File

@ -0,0 +1,50 @@
package org.apache.lucene;
import junit.framework.TestCase;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Hit;
import org.apache.lucene.search.HitIterator;
/**
* This test intentionally not put in the search package in order
* to test HitIterator and Hit package protection.
*/
public class TestHitIterator extends TestCase {
public void testIterator() throws Exception {
RAMDirectory directory = new RAMDirectory();
IndexWriter writer = new IndexWriter(directory, new WhitespaceAnalyzer(), true);
Document doc = new Document();
doc.add(new Field("field", "iterator test doc 1", Field.Store.YES, Field.Index.TOKENIZED));
writer.addDocument(doc);
doc = new Document();
doc.add(new Field("field", "iterator test doc 2", Field.Store.YES, Field.Index.TOKENIZED));
writer.addDocument(doc);
writer.close();
IndexSearcher searcher = new IndexSearcher(directory);
Hits hits = searcher.search(new TermQuery(new Term("field", "iterator")));
HitIterator iterator = (HitIterator) hits.iterator();
assertEquals(2, iterator.length());
assertTrue(iterator.hasNext());
Hit hit = (Hit) iterator.next();
assertEquals("iterator test doc 1", hit.get("field"));
assertTrue(iterator.hasNext());
hit = (Hit) iterator.next();
assertEquals("iterator test doc 2", hit.getDocument().get("field"));
assertFalse(iterator.hasNext());
}
}