cancel
Showing results for 
Search instead for 
Did you mean: 

Custom attribute facets are not displaying in storefront?

0 Kudos

Hi,

We have added some custom attribute to product model.

<attribute qualifier="length" type="java.lang.Double">
<persistence type="property"></persistence>
</attribute>

configured the above attribute in solr.impex file like below

# Define price range set
INSERT_UPDATE SolrValueRangeSet;name[unique=true];qualifier;type;solrValueRanges(⦥ValueRefID)
;lengthRange;length;double;lengthRangeRef1,lengthRangeRef2,lengthRangeRef3,lengthRangeRef4,lengthRangeRef5
# Define price ranges
INSERT_UPDATE SolrValueRange;⦥ValueRefID;solrValueRangeSet(name)[unique=true];name[unique=true];from;to
;lengthRangeRef1;lengthRange;      0-49.99;   0;  49.99
;lengthRangeRef2;lengthRange;    50-99.99;  50; 99.99
;lengthRangeRef3;lengthRange;   100-149.99; 100; 149.99
;lengthRangeRef4;lengthRange;   150-199.99; 150; 199.99
;lengthRangeRef5;lengthRange;200-300;200; 300
# Other facet properties
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true];name[unique=true];type(code);sortableType(code);currency[default=false];localized[default=false];multiValue[default=false];facet[default=true];facetType(code);facetSort(code);priority;visible;useForSpellchecking[default=false];useForAutocomplete[default=false];fieldValueProvider;facetDisplayNameProvider;customFacetSortProvider;topValuesProvider;rangeSets(name)
;$solrIndexedType; length;double; ;     ;     ;true ;     ;MultiSelectOr ;Alpha;10000;true;     ;     ;bobstProductSizeValueProvider;;;defaultTopValuesProvider;lengthRange

# Facet search query properties
INSERT_UPDATE SolrSearchQueryProperty;indexedProperty(name, solrIndexedType(identifier))[unique=true];facet[default=true];facetType(code);priority;facetDisplayNameProvider;facetSortProvider;facetTopValuesProvider;includeInResponse[default=true];searchQueryTemplate(name, indexedType(identifier))[unique=true][default=DEFAULT:$solrIndexedType]
;length:$solrIndexedType;;MultiSelectOr;10000;;;;;

value provider is:

public class ProductLengthValueProvider extends AbstractPropertyFieldValueProvider
implements FieldValueProvider, Serializable {
private static final Logger logger = LoggerFactory.getLogger(BobstProductLengthValueProvider.class);
private FieldNameProvider fieldNameProvider;
@Override
public Collection<FieldValue> getFieldValues(final IndexConfig indexConfig, final IndexedProperty indexedProperty,
final Object model) throws FieldValueProviderException {
if (model instanceof ProductModel) {
final ProductModel product = (ProductModel) model;
final List<FieldValue> fieldValues = createFieldValue(product, indexConfig, indexedProperty);
return fieldValues;
} else {
throw new FieldValueProviderException("Cannot get length for a product model");
}
}
protected List<FieldValue> createFieldValue(final ProductModel model, final IndexConfig indexConfig,
final IndexedProperty indexedProperty) {
final List<FieldValue> fieldValues = new ArrayList<FieldValue>();
final String qualifier = indexedProperty.getName();
Object result = null;
result = modelService.getAttributeValue(model, qualifier);
logger.info("Length attribute value: ...................." + result + " For product code: " + model.getCode());
if (result != null) {
addFieldValues(fieldValues, indexedProperty, null, result);
}
return fieldValues;
}
protected void addFieldValues(final List<FieldValue> fieldValues, final IndexedProperty indexedProperty,
final LanguageModel language, final Object value) {
final Collection<String> fieldNames = getFieldNameProvider().getFieldNames(indexedProperty,
(language == null) ? null : language.getIsocode());
for (final String fieldName : fieldNames) {
fieldValues.add(new FieldValue(fieldName, value));
}
}
public FieldNameProvider getFieldNameProvider() {
return fieldNameProvider;
}
public void setFieldNameProvider(final FieldNameProvider fieldNameProvider) {
this.fieldNameProvider = fieldNameProvider;
}
}

I have imported the above script and ran the solr indexing from backoffice. while indexing configured value provider will be executed and indexing succeeded. But, custom attribute facets are not displaying in storefront.

Please let me know If I miss anything here.

Can anyone please help with this. If sample code provided will be appreciated.

Thanks in advance!

Regards

Praveen

Accepted Solutions (0)

Answers (1)

Answers (1)

aimprosoft
Participant
0 Kudos

Hi Praveen,

I have reviewed your code and configuration.

I have found the reason why your ValueProvider is working (you can see log entry and see value in Solr), but the facet is missing on the storefront.

You made one mistake. You provided value for Solr. It's a mistake if you use ranges.

This line below is incorrect:

fieldValues.add(new FieldValue(fieldName, value));

For ranges, you need to specify range name instead of value. (You can find example in the default implementation, check `ProductPriceValueProvider`)

fieldValues.add(new FieldValue(fieldName, rangeName));

Moreover, you don’t need a valueProvider at all for your purposes.

In Hybris, if you don’t specify any provider, "ModelPropertyFieldValueProvider" will be used.

This provider can also handle ranges. In addition to that, it will provide functionality that you require. Take a look at the image below:

If you want to use a default value provider, you’ll need to fix your rangeSet name.

INSERT_UPDATE SolrValueRangeSet;name[unique=true];qualifier;type;solrValueRanges(&ValueRefID)
;lengthRange;default;double;lengthRangeRef1,lengthRangeRef2,lengthRangeRef3,lengthRangeRef4,lengthRangeRef5

Since default provider uses "DefaultRangeNameProvider.getValueRanges" method to find ranges, use the value “default” if you have only one range name or use language ISO-code.

You can check the implementation below:

if (qualifier == null)
{
   valueRangeSet = (ValueRangeSet) property.getValueRangeSets().get("default");
}
else
{
   valueRangeSet = (ValueRangeSet) property.getValueRangeSets().get(qualifier);
   if (valueRangeSet == null)
   {
      valueRangeSet = (ValueRangeSet) property.getValueRangeSets().get("default");
   }
}

qualifier – for default provider – it’s language ISO-code.

However, I see that you don’t need localization, so you can just use the value "default" for the field "qualifier".

Also, one more thing. It’s desirable to use more meaningful and distinct names for attributes and variables when it comes to size, lengths of the product, its amount, etc.

I hope this answers your question.

Best regards,

Igor

Hi Igor,

Thank you very much for your reply. Actually, we found the issue that, If indexed property doesn't have sortProvider then it's clearing the all the range values while retrieving the ranges from solr. So we have used OTB sort provider, now it's working as expected.

Yes, you are right. we can use 'ModelPropertyFieldValueProvider', but if the product model attribute having no value, its returning null pointer exception, because of that reason we have used custom value provider to do the null check.

Regards,

Praveen