[hibernate-dev] [HSearch] Faceting feedback

Hardy Ferentschik hibernate at ferentschik.de
Mon Feb 28 10:13:43 EST 2011


Hi,

I thought it would be great to get some feedback on my faceting work.
You can see the latest on my Search fork -  
https://github.com/hferentschik/hibernate-search/commits/HSEARCH-667

Technically I decided to use a simple custom Collector. I abandoned the  
idea for using bobo browse, since it did
not really seem to fit our architecture and I am not sure how well  
maintained the code is.
Within the custom Collector I am using Lucene's FieldCache to cache and  
collect the count values during facting
(as a reminder, faceting for example means that I am searching for all  
cars or a certain make, but then also want
to group the matching cars into their cubic capacity. See also -  
http://en.wikipedia.org/wiki/Faceted_search)
Using the FieldCache is quite memory costly, but there are other ways to  
implement the faceting itself.

At the moment I am mostly interested in the feedback around the public  
API. The public classes can be found in
the package org.hibernate.search.query.facet -  
https://github.com/hferentschik/hibernate-search/tree/3a9877e2bbc47a8bd6e438dbbab56d93ac9101fd/hibernate-search/src/main/java/org/hibernate/search/query/facet

The idea is to write a fulltext query as usual and then add/enable a facet:

FacetRequest request = new SimpleFacetRequest( indexFieldName,  
FacetSortOrder.COUNT_DESC, false );
TermQuery term = new TermQuery( new Term( "make", "honda" ) );
FullTextQuery query = fullTextSession.createFullTextQuery( term, Car.class  
);
query.enableQueryFacet( "foo", request );

Then you run the query. This will enable the facet collector and after the  
query executed you get access to a map
which maps FacetResults to the facet name. Each FacetResult contains a  
list of Facets which contain the actually
field values and counts:

Map<String, FacetResult> results = query.getFacetResults();
FacetResult facetResult = results.get( "foo" );
List<Facet> facetList = facetResult.getFacets();
assertEquals( "Wrong facet count for facet ", 100, facetList.get( 0  
).getCount() );

More actual tests can be found here -  
https://github.com/hferentschik/hibernate-search/tree/3a9877e2bbc47a8bd6e438dbbab56d93ac9101fd/hibernate-search/src/test/java/org/hibernate/search/test/query/facet

At the moment you are able to facet on simple (string) based values or on  
number ranges (eg price ranges 0 - 100, ...). For that I have created  
subclasses of
FacetRequest - SimpleFacetRequest and RangeFacetRequest (a  
DateRangeFacetRequest might be interesting as well)

Some concrete questions:
* Atm, I am only exposing a programmatic API for creating FacetRequests. I  
guess we want to have annotations for this as well, right?
   Would we keep the programmatic configuration as a public API?
* I made the FacetRequest classes immutable atm, but this way I have a  
multitude of constructors catering for a whole range of parameters
   (sort order, include zero counts, ...). Any opinions around immutable  
objects vs objects with setters for configuring options after creation.

If course I am interested in any other feedback as well.

--Hardy



 



More information about the hibernate-dev mailing list