Smile-SA / elasticsuite

Smile ElasticSuite - Magento 2 merchandising and search engine built on ElasticSearch
https://elasticsuite.io
Open Software License 3.0
761 stars 341 forks source link

Decimal values in attribute, attribute not appearing on layered nav #1672

Open joeldavuk opened 4 years ago

joeldavuk commented 4 years ago

Preconditions

Magento Version : CE ElasticSuite Version : 2.8.3 Environment : Develop/Prod Third party modules : None

Steps to reproduce

  1. Add text attribute with Frontend validation to decimal
  2. Add 3 products each with the text attribute set to one of these values 25.0, 25.0, 25.4
  3. Set the filter to "Always displayed" on the category display options

Expected result

  1. Range slider should appear in the left hand nav on a category page

Actual result

  1. Filter is not shown, If I modify one of the values to 26 the filter is shown
romainruaud commented 4 years ago

Hi @joeldavuk , we'll have a look on this one.

Maybe it's due to the fact that all your values are in a too small interval (they are considered as all being "25"). Legacy Elasticsearch (2.x) was not supporting decimal ranges so maybe we designed our implementation accordingly when we wrote it.

We'll keep you in touch.

Regards

rbayet commented 4 years ago

Hello @joeldavuk,

As it stands, the Elasticsuite slider does not support indeed sub unit filtering.

The filter for decimal attributes uses an histogram aggregation. The histogram aggregation performs a Math.floor on the values to determine the aggregation bucket they belong with the following formula :

bucket_key = Math.floor((value - offset) / interval) * interval + offset

Where offset and interval are the parameters of the aggregation.

We do not provide an offset value and our interval is always 1. (See \Smile\ElasticsuiteCore\Search\Request\Aggregation\Bucket\Histogram which accepts an interval parameter, defaulting to 1 and \Smile\ElasticsuiteCatalog\Search\Request\Product\Attribute\Aggregation\Decimal which does not provide one)

So the formula is :

bucket_key = Math.floor((value) / 1) * 1 = Math.floor(value)

So the bucket key for your values 25.0 and 25.4 end up being the same (25) and we do not show the slider where there is a single value.

If you were to alter the value of the interval parameter to 0.5 (for instance with an after plugin on \Smile\ElasticsuiteCatalog\Search\Request\Product\Attribute\Aggregation\Decimal::getAggregationData), you would still get only one bucket and no slider with the values 25.0 and 25.4 :

If you were to have 25.0, 25.4 and 25.6 as values and if you were to alter the value of the internal parameter as described above, you would face another issue :

    /**
     * Return field faceted data from faceted search result.
     *
     * @param string $field Facet field.
     *
     * @return array
     */
    public function getFacetedData($field)
    {
        $this->_renderFilters();
        $result = [];
        $aggregations = $this->queryResponse->getAggregations();

        $bucket = $aggregations->getBucket($field);

        if ($bucket) {
            foreach ($bucket->getValues() as $value) {
                $metrics = $value->getMetrics();
                $result[$value->getValue()] = $metrics; // <== the bucket 25.5 will overwrite the values of the bucket 25 with 25 as key.
            }
        }

        return $result;
    }

I haven't looked further than that and didn't test what would happen when applying a range with decimal values.

Feel free to submit a feature request and/or if you end up implementing it, we would gladly review and accept a PR from you.

Regards,