[hibernate-commits] Hibernate SVN: r11518 - in trunk/HibernateExt/search/src: java/org/hibernate/search/impl and 2 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Sun May 13 18:05:25 EDT 2007
Author: epbernard
Date: 2007-05-13 18:05:24 -0400 (Sun, 13 May 2007)
New Revision: 11518
Added:
trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQuery.java
trunk/HibernateExt/search/src/test/org/hibernate/search/test/query/LuceneQuerySortTest.java
Modified:
trunk/HibernateExt/search/src/java/org/hibernate/search/FullTextSession.java
trunk/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java
trunk/HibernateExt/search/src/java/org/hibernate/search/query/IteratorImpl.java
Log:
HSEARCH-4 Support for Lucene sort (Hardy Ferentschik)
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/FullTextSession.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/FullTextSession.java 2007-05-13 21:21:11 UTC (rev 11517)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/FullTextSession.java 2007-05-13 22:05:24 UTC (rev 11518)
@@ -3,6 +3,7 @@
import org.hibernate.classic.Session;
import org.hibernate.Query;
+import org.hibernate.search.query.FullTextQuery;
/**
* Extends the Hibernate {@link Session} with Full text search and indexing capabilities
@@ -15,7 +16,7 @@
* of type <code>entities</code> and their respective subclasses.
* If no entity is provided, no type filtering is done.
*/
- Query createFullTextQuery(org.apache.lucene.search.Query luceneQuery, Class... entities);
+ FullTextQuery createFullTextQuery(org.apache.lucene.search.Query luceneQuery, Class... entities);
/**
* Force the (re)indexing of a given <b>managed</b> object.
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java 2007-05-13 21:21:11 UTC (rev 11517)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java 2007-05-13 22:05:24 UTC (rev 11518)
@@ -45,6 +45,7 @@
import org.hibernate.search.backend.WorkType;
import org.hibernate.search.engine.DocumentBuilder;
import org.hibernate.search.query.FullTextQueryImpl;
+import org.hibernate.search.query.FullTextQuery;
import org.hibernate.search.util.ContextHelper;
import org.hibernate.stat.SessionStatistics;
import org.hibernate.type.Type;
@@ -71,7 +72,7 @@
*
* @param entities must be immutable for the lifetime of the query object
*/
- public Query createFullTextQuery(org.apache.lucene.search.Query luceneQuery, Class... entities) {
+ public FullTextQuery createFullTextQuery(org.apache.lucene.search.Query luceneQuery, Class... entities) {
return new FullTextQueryImpl( luceneQuery, entities, sessionImplementor, new ParameterMetadata(null, null) );
}
Added: trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQuery.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQuery.java (rev 0)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQuery.java 2007-05-13 22:05:24 UTC (rev 11518)
@@ -0,0 +1,33 @@
+//$Id: $
+package org.hibernate.search.query;
+
+import org.apache.lucene.search.Sort;
+import org.hibernate.Query;
+
+/**
+ * The base interface for lucene powered searches.
+ *
+ * @author Hardy Ferentschik
+ */
+public interface FullTextQuery extends Query {
+ //todo Determine what other lucene specific features to expose via this
+ // interface. Maybe we should give access to the underlying lucene hit
+ // objects?
+
+ /**
+ * Allows to let lucene sort the results. This is useful when you have
+ * additional sort requirements on top of the default lucene ranking.
+ * Without lucene sorting you would have to retrieve the full result set and
+ * order the hibernate objects.
+ *
+ * @param sort The lucene sort object.
+ */
+ void setSort(Sort sort);
+
+ /**
+ * Returns the number of hits for this search
+ *
+ * @return The number of hits for this search
+ */
+ int resultSize();
+}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java 2007-05-13 21:21:11 UTC (rev 11517)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java 2007-05-13 22:05:24 UTC (rev 11518)
@@ -22,6 +22,7 @@
import org.apache.lucene.search.MultiSearcher;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.Sort;
import org.apache.lucene.store.Directory;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
@@ -39,10 +40,13 @@
import org.hibernate.search.util.ContextHelper;
/**
+ * Implementation of {@link org.hibernate.search.query.FullTextQuery}
+ *
* @author Emmanuel Bernard
+ * @author Hardy Ferentschik
*/
//TODO implements setParameter()
-public class FullTextQueryImpl extends AbstractQueryImpl {
+public class FullTextQueryImpl extends AbstractQueryImpl implements FullTextQuery {
private static final Log log = LogFactory.getLog( FullTextQueryImpl.class );
private org.apache.lucene.search.Query luceneQuery;
private Class[] classes;
@@ -50,6 +54,7 @@
private Integer firstResult;
private Integer maxResults;
private int resultSize;
+ private Sort sort;
/**
* classes must be immutable
@@ -62,6 +67,11 @@
this.classes = classes;
}
+
+ public void setSort(Sort sort) {
+ this.sort = sort;
+ }
+
/**
* Return an interator on the results.
* Retrieve the object one by one (initialize it during the next() operation)
@@ -79,8 +89,7 @@
return new IteratorImpl( new ArrayList<EntityInfo>(0), (Session) this.session);
}
try {
- org.apache.lucene.search.Query query = filterQueryByClasses( luceneQuery );
- Hits hits = searcher.search( query );
+ Hits hits = getHits( searcher );
setResultSize( hits );
int first = first();
int max = max( first, hits );
@@ -118,8 +127,7 @@
//FIXME: handle null searcher
Hits hits;
try {
- org.apache.lucene.search.Query query = filterQueryByClasses( luceneQuery );
- hits = searcher.search( query );
+ hits = getHits( searcher );
setResultSize( hits );
int first = first();
int max = max( first, hits );
@@ -148,8 +156,7 @@
if (searcher == null) return new ArrayList(0);
Hits hits;
try {
- org.apache.lucene.search.Query query = filterQueryByClasses( luceneQuery );
- hits = searcher.search( query );
+ hits = getHits( searcher );;
setResultSize( hits );
int first = first();
int max = max( first, hits );
@@ -193,6 +200,25 @@
}
}
+ /**
+ * Execute the lucene search and return the machting hits.
+ *
+ * @param searcher The index searcher.
+ * @return The lucene hits.
+ * @throws IOException in case there is an error executing the lucene search.
+ */
+ private Hits getHits(Searcher searcher) throws IOException {
+ Hits hits;
+ org.apache.lucene.search.Query query = filterQueryByClasses( luceneQuery );
+ if(sort == null){
+ hits = searcher.search( query );
+ }
+ else {
+ hits = searcher.search( query, sort );
+ }
+ return hits;
+ }
+
private org.apache.lucene.search.Query filterQueryByClasses(org.apache.lucene.search.Query luceneQuery) {
//A query filter is more practical than a manual class filtering post query (esp on scrollable resultsets)
//it also probably minimise the memory footprint
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/query/IteratorImpl.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/query/IteratorImpl.java 2007-05-13 21:21:11 UTC (rev 11517)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/query/IteratorImpl.java 2007-05-13 22:05:24 UTC (rev 11518)
@@ -17,43 +17,43 @@
private final Session session;
private int index = 0;
private final int size;
- private Object next;
- private int nextObjectIndex = -1;
+ private Object next;
+ private int nextObjectIndex = -1;
- public IteratorImpl(List<EntityInfo> entityInfos, Session session) {
+ public IteratorImpl(List<EntityInfo> entityInfos, Session session) {
this.entityInfos = entityInfos;
this.session = session;
this.size = entityInfos.size();
}
- //side effect is to set up next
- public boolean hasNext() {
- if (nextObjectIndex == index) return next != null;
- next = null;
- nextObjectIndex = -1;
- do {
- if ( index >= size ) {
- nextObjectIndex = index;
- next = null;
- return false;
- }
- next = session.get( entityInfos.get( index ).clazz, entityInfos.get( index ).id );
- if (next == null) {
- index++;
- }
- else {
- nextObjectIndex = index;
- }
- }
- while( next == null );
- return true;
- }
+ //side effect is to set up next
+ public boolean hasNext() {
+ if ( nextObjectIndex == index ) return next != null;
+ next = null;
+ nextObjectIndex = -1;
+ do {
+ if ( index >= size ) {
+ nextObjectIndex = index;
+ next = null;
+ return false;
+ }
+ next = session.get( entityInfos.get( index ).clazz, entityInfos.get( index ).id );
+ if ( next == null ) {
+ index++;
+ }
+ else {
+ nextObjectIndex = index;
+ }
+ }
+ while ( next == null );
+ return true;
+ }
public Object next() {
- //hasNext() has side effect
- if ( ! hasNext() ) throw new NoSuchElementException("Out of boundaries");
- index++;
- return next;
+ //hasNext() has side effect
+ if ( !hasNext() ) throw new NoSuchElementException( "Out of boundaries" );
+ index++;
+ return next;
}
public void remove() {
Added: trunk/HibernateExt/search/src/test/org/hibernate/search/test/query/LuceneQuerySortTest.java
===================================================================
--- trunk/HibernateExt/search/src/test/org/hibernate/search/test/query/LuceneQuerySortTest.java (rev 0)
+++ trunk/HibernateExt/search/src/test/org/hibernate/search/test/query/LuceneQuerySortTest.java 2007-05-13 22:05:24 UTC (rev 11518)
@@ -0,0 +1,100 @@
+//$Id: $
+package org.hibernate.search.test.query;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.lucene.analysis.StopAnalyzer;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
+import org.hibernate.Transaction;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.Version;
+import org.hibernate.search.query.FullTextQuery;
+import org.hibernate.search.test.SearchTestCase;
+
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class LuceneQuerySortTest extends SearchTestCase {
+
+ /**
+ * Class logger.
+ */
+ private static Log log = LogFactory.getLog( Version.class );
+
+ /**
+ * Test that we can change the default sort order of the lucene search result.
+ *
+ * @throws Exception in case the test fails.
+ */
+ public void testList() throws Exception {
+ FullTextSession s = Search.createFullTextSession( openSession() );
+ createTestBooks(s);
+ Transaction tx = s.beginTransaction();
+ QueryParser parser = new QueryParser("title", new StopAnalyzer() );
+
+ Query query = parser.parse( "summary:lucene" );
+ FullTextQuery hibQuery = s.createFullTextQuery( query, Book.class );
+ List<Book> result = hibQuery.list();
+ assertNotNull( result );
+ assertEquals( "Wrong number of test results.", 3, result.size() );
+ // make sure that the order is according to in which order the books got inserted
+ // into the index.
+ int id = 1;
+ for(Book b : result) {
+ assertEquals("Expected another id", new Integer(id), b.getId());
+ id++;
+ }
+
+ // now the same query, but with a lucene sort specified.
+ query = parser.parse( "summary:lucene" );
+ hibQuery = s.createFullTextQuery( query, Book.class );
+ Sort sort = new Sort(new SortField("id", true));
+ hibQuery.setSort(sort);
+ result = hibQuery.list();
+ assertNotNull( result );
+ assertEquals( "Wrong number of test results.", 3, result.size() );
+ id = 3;
+ for(Book b : result) {
+ assertEquals("Expected another id", new Integer(id), b.getId());
+ id--;
+ }
+
+
+ tx.commit();
+ s.close();
+ }
+
+ /**
+ * Helper method creating three books with the same title and summary.
+ * When searching for these books the results should be returned in the order
+ * they got added to the index.
+ *
+ * @param s The full text session used to index the test data.
+ */
+ private void createTestBooks(FullTextSession s) {
+ Transaction tx = s.beginTransaction();
+ Book book = new Book(1, "Hibernate & Lucene", "This is a test book.");
+ s.save(book);
+ book = new Book(2, "Hibernate & Lucene", "This is a test book.");
+ s.save(book);
+ book = new Book(3, "Hibernate & Lucene", "This is a test book.");
+ s.save(book);
+ tx.commit();
+ s.clear();
+ }
+
+ protected Class[] getMappings() {
+ return new Class[] {
+ Book.class,
+ AlternateBook.class,
+ Clock.class
+ };
+ }
+}
More information about the hibernate-commits
mailing list