Skip to content

Instantly share code, notes, and snippets.

@emmanuelbernard
Created March 14, 2011 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emmanuelbernard/869145 to your computer and use it in GitHub Desktop.
Save emmanuelbernard/869145 to your computer and use it in GitHub Desktop.
Version where the faceting filter state is managed by Hibernate Search
/**
* @author Emmanuel Bernard <emmanuel@hibernate.org>
*/
public class SearchServiceV2 {
@Inject
FullTextEntityManager em;
private org.hibernate.search.FullTextQuery ftQuery;
/**
* do the initial query
*/
public List<Car> searchCar(String queryString) {
final QueryBuilder builder = em.getSearchFactory().buildQueryBuilder().forEntity( Car.class ).get();
final Query query = builder.bool()
.should( builder.keyword().onField( "model" ).matching( queryString ).createQuery() )
.should( builder.keyword().onField( "make" ).matching( queryString ).createQuery() )
.createQuery();
final FacetRequest colorFacet = builder.facet().name( "color" ).onField( "color" ).discrete().createFacet();
final FacetRequest priceFacet = builder.facet().name( "price" ).onField( "color" )
.range()
.from( 0 ).to( 5000 ).excludeLimit()
.from( 5000 ).to( 15000 ).excludeLimit()
.from( 15000 ).to( Integer.MAX_VALUE ) //fix with .above(15000)
.createFacet();
//FIXME jpa.FTQuery does not have the facet methods, need to do some nasty unwrapping
ftQuery = em.unwrap( FullTextSession.class )
.createFullTextQuery( query, Car.class );
ftQuery.setFirstResult( 0 ).setMaxResults( 20 );
ftQuery.enableFacet( colorFacet ).enableFacet( priceFacet );
final List results = ftQuery.list();
return results;
}
/**
* Simulate display of facets on the left side (like Amazon)
*/
public void displayFacets() {
StringBuilder sb = new StringBuilder();
for ( FacetResult facetResult : ftQuery.getFacetResults().values() ) {
sb.append( facetResult.getName() ).append( "\n" );
//TODO should the index be included in object Facet? Not sure but worth thinking about
for ( int index = 0; index < facetResult.getFacets().size(); index++ ) {
Facet facet = facetResult.getFacets().get( index );
FacetRequestV2 facetRequest = ftQuery.getFacetRequests().get( facetResult.getName() );
final boolean facetSelected = facetRequest.getSelectedFacets().contains( facet );
sb.append( "\t" );
if ( facetSelected ) {
sb.append( "[UNSELECT]" );
}
else {
sb.append( "[SELECT]" );
}
sb.append( facet.getValue() ).append( " (" ).append( facet.getCount() ).append( ")" )
.append( " hidden index: " ).append( index );
}
}
}
/**
* method called on a click to a discrete facet. discrete facets are usually multiselectable (like Amazon)
*/
public List<Car> selectOrDeselectFacetFilterAndReturnResults(String facetName, int element) {
FacetRequestV2 facetRequest = ftQuery.getFacetRequests().get( facetName );
final FacetResult facetResult = ftQuery.getFacetResults().get( facetName );
final Facet facet = facetResult.getFacets().get( element );
if ( facetRequest.getSelectedFacets().contains( facet ) ) {
facetRequest.unselectFacet( facet );
}
else {
facetRequest.selectFacet( facet );
}
final List results = ftQuery.list();
return results;
}
//Changes to FacetRequest
public abstract class FacetRequestV2 extends FacetRequest {
public FacetRequestV2(String name, String fieldName) {
super( name, fieldName );
}
public void selectFacet(Facet facet) {
}
;
public void unselectFacet(Facet facet) {
}
;
public void clearSelectedFacet() {
}
;
public List<Facet> getSelectedFacets() {
return null;
}
;
public void setSelectedFacets(List<Facet> facets) {
}
;
}
//Changes to FTQuery
//add getFacetRequests()
}
@hferentschik
Copy link

For me adding these facet selection methods on the request seems wrong. I think the facet definition (done in FacetRequest) is orthogonal to the facet definition. Also how do you know that the Facet added via selectFacet belongs to this request. It could be from a facet request on a different field. Do you accept it or do you throw on exception.
A good point about your example is, however, is that I should be able to OR combine two facets (as you say some sort of multiselect)
I wonder whether you FacetManager would make sense here. If we push the facet selection and deselection into it it might get more useful than just being a container to bundle facet related methods

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment