[hibernate-commits] Hibernate SVN: r14719 - in search/trunk/src: java/org/hibernate/search/impl and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri May 30 18:28:11 EDT 2008


Author: epbernard
Date: 2008-05-30 18:28:11 -0400 (Fri, 30 May 2008)
New Revision: 14719

Modified:
   search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java
   search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
   search/trunk/src/java/org/hibernate/search/query/FullTextQueryImpl.java
   search/trunk/src/java/org/hibernate/search/store/DirectoryProviderFactory.java
   search/trunk/src/test/org/hibernate/search/test/RamDirectoryTest.java
Log:
HSEARCH-19 no longer filter classes when DPs contains all the targeted classes

Modified: search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java	2008-05-30 22:26:13 UTC (rev 14718)
+++ search/trunk/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java	2008-05-30 22:28:11 UTC (rev 14719)
@@ -2,6 +2,7 @@
 package org.hibernate.search.engine;
 
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.hibernate.search.SearchFactory;
@@ -44,4 +45,8 @@
 	public String getIndexingStrategy();
 
 	public void close();
+
+	void addClassToDirectoryProvider(Class clazz, DirectoryProvider<?> directoryProvider);
+
+	Set<Class> getClassesInDirectoryProvider(DirectoryProvider<?> directoryProvider);
 }

Modified: search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java	2008-05-30 22:26:13 UTC (rev 14718)
+++ search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java	2008-05-30 22:28:11 UTC (rev 14719)
@@ -4,7 +4,9 @@
 import java.beans.Introspector;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -13,6 +15,7 @@
 import java.util.WeakHashMap;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.apache.lucene.analysis.Analyzer;
 import org.hibernate.annotations.common.reflection.ReflectionManager;
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
@@ -43,7 +46,6 @@
 import org.hibernate.search.store.DirectoryProvider;
 import org.hibernate.search.store.DirectoryProviderFactory;
 import org.hibernate.search.store.optimization.OptimizerStrategy;
-import org.apache.lucene.analysis.Analyzer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,10 +64,11 @@
 
 	private final Map<Class, DocumentBuilder<Object>> documentBuilders = new HashMap<Class, DocumentBuilder<Object>>();
 	//keep track of the index modifiers per DirectoryProvider since multiple entity can use the same directory provider
+	//TODO move the ReentrantLock into DirectoryProviderData.lock, add a getDPLock(DP) and add a Set<DP> getDirectoryProviders() method.
 	private final Map<DirectoryProvider, ReentrantLock> lockableDirectoryProviders =
 			new HashMap<DirectoryProvider, ReentrantLock>();
-	private final Map<DirectoryProvider, OptimizerStrategy> dirProviderOptimizerStrategies =
-			new HashMap<DirectoryProvider, OptimizerStrategy>();
+	private final Map<DirectoryProvider, DirectoryProviderData> dirProviderData =
+			new HashMap<DirectoryProvider, DirectoryProviderData>();
 	private Worker worker;
 	private ReaderProvider readerProvider;
 	private BackendQueueProcessorFactory backendQueueProcessorFactory;
@@ -139,6 +142,19 @@
 		}
 	}
 
+	public void addClassToDirectoryProvider(Class clazz, DirectoryProvider<?> directoryProvider) {
+		DirectoryProviderData data = dirProviderData.get(directoryProvider);
+		if (data == null) {
+			data = new DirectoryProviderData();
+			dirProviderData.put( directoryProvider, data );
+		}
+		data.classes.add(clazz);
+	}
+
+	public Set<Class> getClassesInDirectoryProvider(DirectoryProvider<?> directoryProvider) {
+		return Collections.unmodifiableSet( dirProviderData.get(directoryProvider).classes );
+	}
+
 	private void bindFilterDefs(XClass mappedXClass) {
 		FullTextFilterDef defAnn = mappedXClass.getAnnotation( FullTextFilterDef.class );
 		if ( defAnn != null ) {
@@ -227,7 +243,12 @@
 	}
 
 	public void addOptimizerStrategy(DirectoryProvider<?> provider, OptimizerStrategy optimizerStrategy) {
-		dirProviderOptimizerStrategies.put( provider, optimizerStrategy );
+		DirectoryProviderData data = dirProviderData.get(provider);
+		if (data == null) {
+			data = new DirectoryProviderData();
+			dirProviderData.put( provider, data );
+		}
+		data.optimizerStrategy = optimizerStrategy;
 	}
 
 	public void addIndexingParameters(DirectoryProvider<?> provider, LuceneIndexingParameters indexingParams) {
@@ -235,7 +256,7 @@
 	}
 
 	public OptimizerStrategy getOptimizerStrategy(DirectoryProvider<?> provider) {
-		return dirProviderOptimizerStrategies.get( provider );
+		return dirProviderData.get( provider ).optimizerStrategy;
 	}
 
 	public LuceneIndexingParameters getIndexingParameters(DirectoryProvider<?> provider ) {
@@ -301,7 +322,7 @@
 				XClass mappedXClass = reflectionManager.toXClass(mappedClass);
 				if ( mappedXClass != null) {
 					if ( mappedXClass.isAnnotationPresent( Indexed.class ) ) {
-						DirectoryProviderFactory.DirectoryProviders providers = factory.createDirectoryProviders( mappedXClass, cfg, this );
+						DirectoryProviderFactory.DirectoryProviders providers = factory.createDirectoryProviders( mappedXClass, cfg, this, reflectionManager );
 
 						final DocumentBuilder<Object> documentBuilder = new DocumentBuilder<Object>(
 								mappedXClass, context, providers.getProviders(), providers.getSelectionStrategy(),
@@ -349,4 +370,9 @@
 	public FilterDef getFilterDefinition(String name) {
 		return filterDefinitions.get( name );
 	}
+
+	private static class DirectoryProviderData {
+		public OptimizerStrategy optimizerStrategy;
+		public Set<Class> classes = new HashSet<Class>(2);
+	}
 }

Modified: search/trunk/src/java/org/hibernate/search/query/FullTextQueryImpl.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/query/FullTextQueryImpl.java	2008-05-30 22:26:13 UTC (rev 14718)
+++ search/trunk/src/java/org/hibernate/search/query/FullTextQueryImpl.java	2008-05-30 22:28:11 UTC (rev 14719)
@@ -69,6 +69,8 @@
 	private org.apache.lucene.search.Query luceneQuery;
 	private Class[] classes;
 	private Set<Class> classesAndSubclasses;
+	//optimization: if we can avoid the filter clause (we can most of the time) do it as it has a significant perf impact
+	private boolean needClassFilterClause;
 	private Integer firstResult;
 	private Integer maxResults;
 	private Integer resultSize;
@@ -384,12 +386,12 @@
 	}
 
 	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
-		if ( classesAndSubclasses == null ) {
+		if ( ! needClassFilterClause ) {
 			return luceneQuery;
 		}
 		else {
+			//A query filter is more practical than a manual class filtering post query (esp on scrollable resultsets)
+			//it also probably minimise the memory footprint	
 			BooleanQuery classFilter = new BooleanQuery();
 			//annihilate the scoring impact of DocumentBuilder.CLASS_FIELDNAME
 			classFilter.setBoost( 0 );
@@ -429,13 +431,13 @@
 		List<DirectoryProvider> directories = new ArrayList<DirectoryProvider>();
 
 		Similarity searcherSimilarity = null;
-
+		//TODO check if caching this work for the last n list of classes makes a perf boost
 		if ( classes == null || classes.length == 0 ) {
 			//no class means all classes
 			for (DocumentBuilder builder : builders.values()) {
 				searcherSimilarity = checkSimilarity( searcherSimilarity, builder );
 				final DirectoryProvider[] directoryProviders = builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForAllShards();
-				populateDirectories( directories, directoryProviders );
+				populateDirectories( directories, directoryProviders, searchFactoryImplementor );
 			}
 			classesAndSubclasses = null;
 		}
@@ -455,11 +457,30 @@
 
 				final DirectoryProvider[] directoryProviders = builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForAllShards();
 				searcherSimilarity = checkSimilarity( searcherSimilarity, builder );
-				populateDirectories( directories, directoryProviders );
+				populateDirectories( directories, directoryProviders, searchFactoryImplementor );
 			}
 			classesAndSubclasses = involvedClasses;
 		}
 
+		//compute optimization needClassFilterClause
+		//if at least one DP contains one class that is not part of the targeted classesAndSubclasses we can't optimize
+		if ( classesAndSubclasses != null) {
+			for (DirectoryProvider dp : directories) {
+				final Set<Class> classesInDirectoryProvider = searchFactoryImplementor.getClassesInDirectoryProvider( dp );
+				// if a DP contains only one class, we know for sure it's part of classesAndSubclasses
+				if ( classesInDirectoryProvider.size() > 1 ) {
+					//risk of needClassFilterClause
+					for (Class clazz : classesInDirectoryProvider) {
+						if ( ! classesAndSubclasses.contains( clazz ) ) {
+							this.needClassFilterClause = true;
+							break;
+						}
+					}
+				}
+				if ( this.needClassFilterClause ) break;
+			}
+		}
+
 		//set up the searcher
 		final DirectoryProvider[] directoryProviders = directories.toArray( new DirectoryProvider[directories.size()] );
 		IndexSearcher is = new IndexSearcher( searchFactoryImplementor.getReaderProvider().openReader( directoryProviders ) );
@@ -467,7 +488,8 @@
 		return is;
 	}
 
-	private void populateDirectories(List<DirectoryProvider> directories, DirectoryProvider[] directoryProviders) {
+	private void populateDirectories(List<DirectoryProvider> directories, DirectoryProvider[] directoryProviders,
+									 SearchFactoryImplementor searchFactoryImplementor) {
 		for (DirectoryProvider provider : directoryProviders) {
 			if ( !directories.contains( provider ) ) {
 				directories.add( provider );

Modified: search/trunk/src/java/org/hibernate/search/store/DirectoryProviderFactory.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/store/DirectoryProviderFactory.java	2008-05-30 22:26:13 UTC (rev 14718)
+++ search/trunk/src/java/org/hibernate/search/store/DirectoryProviderFactory.java	2008-05-30 22:28:11 UTC (rev 14719)
@@ -51,7 +51,9 @@
 	private static final String SHARDING_STRATEGY = "sharding_strategy";
 	private static final String NBR_OF_SHARDS = SHARDING_STRATEGY + ".nbr_of_shards";
 
-	public DirectoryProviders createDirectoryProviders(XClass entity, Configuration cfg, SearchFactoryImplementor searchFactoryImplementor) {
+	public DirectoryProviders createDirectoryProviders(XClass entity, Configuration cfg,
+													   SearchFactoryImplementor searchFactoryImplementor,
+													   ReflectionManager reflectionManager) {
 		//get properties
 		String directoryProviderName = getDirectoryProviderName( entity, cfg );
 		Properties[] indexProps = getDirectoryProperties( cfg, directoryProviderName );
@@ -63,7 +65,8 @@
 			String providerName = nbrOfProviders > 1 ?
 					directoryProviderName + "." + index :
 					directoryProviderName;
-			providers[index] = createDirectoryProvider( providerName, indexProps[index], searchFactoryImplementor );
+			providers[index] = createDirectoryProvider( providerName, indexProps[index],
+					reflectionManager.toClass( entity ), searchFactoryImplementor );
 		}
 
 		//define sharding strategy
@@ -110,7 +113,8 @@
 		}
 	}
 
-	private DirectoryProvider<?> createDirectoryProvider(String directoryProviderName, Properties indexProps, SearchFactoryImplementor searchFactoryImplementor) {
+	private DirectoryProvider<?> createDirectoryProvider(String directoryProviderName, Properties indexProps,
+														 Class entity, SearchFactoryImplementor searchFactoryImplementor) {
 		String className = indexProps.getProperty( "directory_provider" );
 		if ( StringHelper.isEmpty( className ) ) {
 			className = DEFAULT_DIRECTORY_PROVIDER;
@@ -135,12 +139,15 @@
 		int index = providers.indexOf( provider );
 		if ( index != -1 ) {
 			//share the same Directory provider for the same underlying store
-			return providers.get( index );
+			final DirectoryProvider<?> directoryProvider = providers.get( index );
+			searchFactoryImplementor.addClassToDirectoryProvider(entity, directoryProvider);
+			return directoryProvider;
 		}
 		else {
 			configureOptimizerStrategy( searchFactoryImplementor, indexProps, provider );
 			configureIndexingParameters( searchFactoryImplementor, indexProps, provider );
 			providers.add( provider );
+			searchFactoryImplementor.addClassToDirectoryProvider(entity, provider);
 			if ( !searchFactoryImplementor.getLockableDirectoryProviders().containsKey( provider ) ) {
 				searchFactoryImplementor.getLockableDirectoryProviders().put( provider, new ReentrantLock() );
 			}

Modified: search/trunk/src/test/org/hibernate/search/test/RamDirectoryTest.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/RamDirectoryTest.java	2008-05-30 22:26:13 UTC (rev 14718)
+++ search/trunk/src/test/org/hibernate/search/test/RamDirectoryTest.java	2008-05-30 22:28:11 UTC (rev 14719)
@@ -2,7 +2,11 @@
 package org.hibernate.search.test;
 
 import org.hibernate.Session;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.TermQuery;
 
 /**
  * @author Emmanuel Bernard
@@ -28,6 +32,11 @@
 
 		s = getSessions().openSession();
 		s.getTransaction().begin();
+		TermQuery q = new TermQuery(new Term("alt_title", "hibernate"));
+		assertEquals( "does not properly filter", 0,
+				Search.createFullTextSession( s ).createFullTextQuery( q, Document.class ).list().size() );
+		assertEquals( "does not properly filter", 1,
+				Search.createFullTextSession( s ).createFullTextQuery( q, Document.class, AlternateDocument.class ).list().size() );
 		s.delete( s.get( AlternateDocument.class, document.getId() ) );
 		s.getTransaction().commit();
 		s.close();




More information about the hibernate-commits mailing list