Hi everybody, I am trying to work with hibernate search facets. I have three use cases :
- Faceting on a simple field -> This is OK.
- Faceting on a Collection of entity (with an IndexEmbeded) -> This is OK.
- Faceting on a simple Collection (like a Collection of String) -> Thi does not work.
This is an example :
@Field(
name = CATEGORIES,
bridge = @FieldBridge(impl = StringCollectionFieldBridge.class),
analyze = Analyze.NO
)
@Facet(forField = CATEGORIES)
@Transient
public Collection<String> getCategories() {
return Lists.newArrayList(
Iterables.transform(
getBooks(),
Bindings.book().category()
)
);
}
I register my facets like this :
private FacetManager getFacetManager() {
return getFullTextQuery().getFacetManager();
}
protected void registerFacet(FacetingRequest facetingRequest) {
getFacetManager().enableFaceting(facetingRequest);
}
protected void registerFacet(String facetName, String fieldPath) {
FacetingRequest facetingRequest =
getFactory().getDefaultQueryBuilder().facet()
.name(facetName)
.onField(fieldPath)
.discrete()
.includeZeroCounts(false)
.createFacetingRequest();
registerFacet(facetingRequest);
}
and get facets values like this :
protected Collection<Facet> getFacets(String facetName) {
return getFacetManager().getFacets(facetName);
}
@Override
public final List<String> listFacetValues(String facetName) {
return Lists.newArrayList(
Iterables.transform(
getFacets(facetName),
new SerializableFunction<Facet, String>() {
@Override
public String apply(Facet facet) {
return facet.getValue();
}
}
)
);
}
So when I perform this code and try to get facets values, I get a list of String like :
["[category1, category3]", "[category4]", "[category2, category5, category6]"]
This is totally normal regarding the code in the Class
org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity
In fact, facets work well on a Collection of entities because it is detected that there is embeded objects. So the method buildDocumentFieldsForEmbeddedObjects is called. In this method, ther is something like this :
case COLLECTION:
Collection<?> collection = objectInitializer.initializeCollection( (Collection<?>) value );
for ( Object collectionValue : collection ) {
buildDocumentFields(
collectionValue,
doc,
faceting,
embeddedTypeMetadata,
fieldToAnalyzerMap,
processedFieldNames,
conversionContext,
objectInitializer,
embeddedBoost,
true
);
}
break;
So it's works because you iterate on each item. Moreover, multivalued (a FacetHandling property) is set to true. However, on my use case, it is not an embeded. So multivalued property is set to false and the method which is called is this buildDocumentFieldsForProperties which called getFacetDocValues method on a collection object. In this method ther is something like this :
case STRING: {
String stringValue = value.toString();
if ( stringValue.isEmpty() ) {
return null;
}
facetField = new SortedSetDocValuesFacetField(
facetMetadata.getFacetName(),
stringValue
);
break;
}
This is applied directly on a collection object. That's why I get the result above. I think I have a solution to fix the issue but I would like to know if this is really an issue or if I misunderstood something. Thanks for the help. |