Skip to content

Instantly share code, notes, and snippets.

@emmanuelbernard
Created March 14, 2011 13:57
Show Gist options
  • Save emmanuelbernard/869143 to your computer and use it in GitHub Desktop.
Save emmanuelbernard/869143 to your computer and use it in GitHub Desktop.
Version with existing API
/**
* @author Emmanuel Bernard <emmanuel@hibernate.org>
*/
public class SearchService {
@Inject
FullTextEntityManager em;
private org.hibernate.search.FullTextQuery ftQuery;
private Map<FacetResult, OrFacetFilter> filtersByFacetResult = new HashMap<FacetResult, OrFacetFilter>();
/**
* 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 );
final boolean facetSelected = filtersByFacetResult.get( facetResult ).getFacets().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) {
final FacetResult facetResult = ftQuery.getFacetResults().get( facetName );
final Facet facet = facetResult.getFacets().get( element );
OrFacetFilter filter = filtersByFacetResult.get( facetResult );
if ( filter == null ) {
//FIXME need the notion of OrFacetFilter to apply a logical Or on Filter results
filter = new OrFacetFilter();
filtersByFacetResult.put( facetResult, filter );
}
if ( filter.getFacets().contains( facet ) ) {
filter.removeFacet( facet );
}
else {
filter.addFacet( facet );
}
AndFilter globalFilter = new AndFilter();
for ( OrFacetFilter orFilter : filtersByFacetResult.values() ) {
globalFilter.add( orFilter );
}
ftQuery.setFilter( globalFilter );
final List results = ftQuery.list();
return results;
}
private class OrFacetFilter extends Filter {
@Override
public DocIdSet getDocIdSet(IndexReader indexReader) throws IOException {
return null;
}
public void addFacet(Facet facet) {
//TODO
}
public void removeFacet(Facet facet) {
//TODO
}
public Set<Facet> getFacets() {
return null; //TODO
}
}
private class AndFilter extends Filter {
public void add(Filter f) {
//TODO
}
@Override
public DocIdSet getDocIdSet(IndexReader indexReader) throws IOException {
return null; //TODO
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment