See [
HSEARCH-726]
Hi,
I just updated to Hibernate Search 3.4.0CR2 and played with faceted search.
In my case, the counts in the returned facets are incorrect. This probably happens when searching on a embedded field with *tomany relation (I will experiment with it more if it's not caused by my code).
Before I create an issue for this, I want to be sure it's not due to bugs in my code.
To illustrate the problem, here is a result (showing the author facet and search results) of a simple query:
Code:
Top 10 authors (faceted search):
Brand Author(2)
My Name 28690(1)
My Name 12970(1)
Search results (Publications):
4 results found in 3 ms., displaying results 1-4
Title: Title1
Authors: My Name 12970, My Name 28690, My Name 20709
Title: Title2
Authors: My Name 12970, Brand Author
Title: Title3
Authors: Brand Author
Title: Title4
Authors: Brand Author
The problem is that the facet count of 'Brand Author' should be 3, 'My Name 12970' should be 2 and 'My Name 20709' should be 1 (and thus being displayed).
Something seems wrong in collecting the facets, or something is wrong in my code.
Here are the related snippets used for getting the facet objects and search results. The methods
facets and
list are using the
same FullTextQuery instance ('query').
Code:
public java.util.List<Facet> facets(String field, int topN) {
org.hibernate.search.query.dsl.QueryBuilder builder = fullTextSession
.getSearchFactory().buildQueryBuilder().forEntity(entityClass)
.get();
FacetingRequest facetReq = builder.facet().name(field).onField(field).discrete().orderedBy(FacetSortOrder.COUNT_DESC).includeZeroCounts(false).maxFacetCount(topN).createFacetingRequest();
if (validateQuery())
return query.getFacetManager().enableFaceting(facetReq)
.getFacets(field);
else{
return new ArrayList<Facet>();
}
.
.
public java.util.List<EntityClass> list() {
if (validateQuery()) {
return (java.util.List<EntityClass>) query.list();
} else
return new ArrayList<EntityClass>();
}
.
.
private boolean validateQuery() {
if (luceneQueryChanged) {
if (!searchTerms.isEmpty()) {
org.apache.lucene.queryParser.QueryParser parser = new org.apache.lucene.queryParser.MultiFieldQueryParser(
luceneVersion, nonNGramSearchFields, fullTextSession
.getSearchFactory().getAnalyzer(entityClass));
try {
luceneQuery = parser.parse(searchTerms);
} catch (org.apache.lucene.queryParser.ParseException pe) {
return false;
}
}
// Match all documents if no search terms are given
else {
luceneQuery = fullTextSession.getSearchFactory()
.buildQueryBuilder().forEntity(entityClass).get().all()
.createQuery();
}
query = fullTextSession.createFullTextQuery(luceneQuery,
entityClass);
luceneQueryChanged = false;
}
query.setFirstResult(offset);
query.setMaxResults(limit);
return true;
}
Code snippets with annotations in data model (this is generated code), both sides of the relation are searchable through an embedded field:
Publication.java:
Code:
@ManyToMany(mappedBy = "_publications", targetEntity = Author.class, fetch = javax.persistence.FetchType.LAZY) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.MERGE}) @org.hibernate.search.annotations.ContainedIn protected java.util.Set<webdsl.generated.domain.Author> _authors = new java.util.LinkedHashSet<webdsl.generated.domain.Author>();
@org.hibernate.search.annotations.IndexedEmbedded(depth = 1, prefix = "authors" + ".") public java.util.Set<webdsl.generated.domain.Author> getAuthors()
{
return _authors;
}
Author.java:
Code:
@ManyToMany(fetch = javax.persistence.FetchType.LAZY) @JoinTable(name = "Author_publications_Publication", joinColumns = {@JoinColumn(name = "Author_id_owner")}, inverseJoinColumns = {@JoinColumn(name = "Publication_id_inverse")}) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.MERGE}) @org.hibernate.search.annotations.ContainedIn protected java.util.Set<webdsl.generated.domain.Publication> _publications = new java.util.LinkedHashSet<webdsl.generated.domain.Publication>();
@org.hibernate.search.annotations.IndexedEmbedded(depth = 1, prefix = "publications" + ".") public java.util.Set<webdsl.generated.domain.Publication> getPublications()
{
return _publications;
}
.
.
.
@javax.persistence.Column(name = "\"_name\"", length = 255) @org.hibernate.annotations.AccessType(value = "field") protected String _name = "";
@org.hibernate.search.annotations.Fields({@org.hibernate.search.annotations.Field(name = "name"), @org.hibernate.search.annotations.Field(index = org.hibernate.search.annotations.Index.UN_TOKENIZED, name = "name_untokenized")}) public String getName()
{
return _name;