As you guys know I've not been comfortable with the idea of
reusing Filter as an implementation as it seem to be it is an implementation detail that
we might change down the road and that is of no interest to the user.
I didn't understand you where exposing the filter, as I said in
previous mail I don't even sure it's the best way to implement it:
likely it is, but we should make sure we can switch approach so
definitely not in the public API.
Instead of bitching abstractly, I've decided to implement a CDI style bean that
implement faceted search to see how the API us used.
Note that I have tried to implement what amazon does
http://www.amazon.com/gp/search/ref=sr_nr_scat_392442011_ln?rh=n%3A392442...
My feature list was:
- multiple facets per query
- ability to select one or more discrete facet values on a given facet (ie brand = epson
or canon)
- ability to display the facet menu on the left
- ability to remember the state of the selected facet values
While implementing it I've found several proposals for enhancement:
- should we rename in thw facet DSL createFacet to createFacetRequest(), as it's the
object returned
I'm +1 to match the return type, but is it really "XRequest", requests
sounds like we do some remote HTTP get. No strong opinion, as I can't
think of anything better.
- does facet work with pagination (ie is not affected) => we did
some optimization around QueryHits when paginating => add a unit test
Yes that's needed, especially as Lucene 3.1 changed the rules. I have
some fixes ready for that but I'm not sure how Faceting is expected to
interact with pagination, so you'd better hardcode your expectations
in a test before I send a pull request changing that all.
- jpa.FullTextQuery does not have the facet methods
- move Facet methods hosted on FTQuery to a FacetManager interface and do
ftQuery.getFacetManager().enableFacet("cdscds");
- make FacetRequest / FacetResults interfaces?
- Facet should implement equals / hashCode or else we cannot remember the facet
selected
- //TODO should the index be included in object Facet? Not sure but worth thinking about
=> probably not if Facet objects change indexes from one query to the other
- should we rename Facet to FacetElement? We seem to talk about Facets as the global
concept whereas Facet the object represent one of the results of the Facet.
The client of the service is as followed
https://gist.github.com/869181
The solution with the current API is as followed
https://gist.github.com/869143
In this implementation:
- I need to keep some kind of state besides the query to remember which facet has been
selected by the user and which one have not been.
- I need to remember this state across query re execution: even if the request (and thus
the facetREsults) are updated, I need to remember this state or the user will yell
- FacetFilter as it is does not solve the problem at had as I need to:
. use a OR filter for selected elements across a Facet
. use AndFilter to aggregate the various facets and filter the results across all of
them
- I ended up writing and manipulating various OrFacetFilter and AndFilter object which
are not exactly easy to play with
I've worked on an alternative API that internalize the management of this facet
element selection so that the whole filter tree can be managed by Hibernate Search itself
and exposed to the user as a service
https://gist.github.com/869145
Query execution and faceting display are of similar complexity. But the select or
deselect method is simpler. Also note that I no longer need to implement or manipulate
And/Or filters myself (and potentially forget to set it).
I have attached the state of the selected facet elements on the FacetRequest (the
FacetResults are destroyed and reset upon requery). We might want to move it up to
FacetManager (not shown here), I ahve not thought about it.
Yes, it looks great. It always takes a user to polish an API.
What do you guys think? If I had to write a book on Hibernate Search,
I'd prefer the second option by a big margin.
Are you having plans? I'd say the second options is better even
without needing to write a book.
Sanne
On 11 mars 2011, at 20:08, Hardy Ferentschik wrote:
> Hi,
>
> sorry for the following lengthy code example, but it is hard to
> demonstrate this much shorter.
> The example shows how you can enable multiple facets and then continuously
> restrict the query result
> by chaining facets into a FacetFilter (which delegates to a ChainedFilter
> underneath). WDYT?
> If you want to see all the code or even get the feature branch -
>
https://github.com/hferentschik/hibernate-search/blob/HSEARCH-706
>
>
> public void testMultipleFacetDrillDown() throws Exception {
> final String ccsFacetName = "ccs";
> final String ccsFacetFieldName = "cubicCapacity";
> FacetRequest ccsFacetRequest = queryBuilder( Car.class ).facet()
> .name( ccsFacetName )
> .onField( ccsFacetFieldName )
> .discrete()
> .createFacet();
>
> final String colorFacetName = "color";
> final String colorFacetFieldName = "color";
> FacetRequest colorFacetRequest = queryBuilder( Car.class ).facet()
> .name( colorFacetName )
> .onField( colorFacetFieldName )
> .discrete()
> .createFacet();
>
> FullTextQuery query = createMatchAllQuery( Car.class );
> query.enableFacet( colorFacetRequest );
> query.enableFacet( ccsFacetRequest );
> assertEquals( "Wrong number of query matches", 50,
query.getResultSize()
> );
>
> List<Facet> colorFacetList = getFacetListForFacet( query,
colorFacetName
> );
> assertFacetCounts( colorFacetList, new int[] { 12, 12, 12, 12, 2 } );
>
> List<Facet> ccsFacetList = getFacetListForFacet( query,
ccsFacetName );
> assertFacetCounts( ccsFacetList, new int[] { 17, 16, 16, 1 } );
>
> FacetFilter facetFilter = new FacetFilter();
> query.setFilter( facetFilter );
>
> facetFilter.addFacet( colorFacetList.get( 0 ) );
> colorFacetList = getFacetListForFacet( query, colorFacetName );
> assertFacetCounts( colorFacetList, new int[] { 12, 0, 0, 0, 0 } );
>
> ccsFacetList = getFacetListForFacet( query, ccsFacetName );
> assertFacetCounts( ccsFacetList, new int[] { 4, 4, 4, 0 } );
>
> facetFilter.addFacet( ccsFacetList.get( 0 ) );
> // needs to set the filter explicitly atm, because I need the query
> state to reset
> query.setFilter( facetFilter );
> colorFacetList = getFacetListForFacet( query, colorFacetName );
> assertFacetCounts( colorFacetList, new int[] { 4, 0, 0, 0, 0 } );
>
> ccsFacetList = getFacetListForFacet( query, ccsFacetName );
> assertFacetCounts( ccsFacetList, new int[] { 4, 0, 0, 0 } );
> }
>
> I like the idea of using Lucene Filters to implement the drilldown for. It
> seems the most natural and the original query stays
> untouched.
>
> --Hardy
>
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/hibernate-dev
_______________________________________________
hibernate-dev mailing list
hibernate-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev