Sorting products in Magento 2 is usually easy – you can sort based on prices, names, or other attributes.

But what if you need Sort the product based on the custom price valueLike the price of market variations, campaign prices, or external price rules?

In Magento 2 with elasticsearch, the solution is Expand indexing and search layers So that your custom price is stored in elasticsearch and used in sorting.

On this blog, we will run step by step through the process.

Step 1: Understand the flow

When the product is indexed in Elasticsearch, Magento maps the product attributes into the JSON document. Sorting only works in an existing field in Elasticsearch.

So, to sort based on special prices, we need:

  1. Add the custom price field to the elasticsearch document (through ProductDataMapper).
  2. Tell Magento How to Complete the Field Name When building questions (via Resolver\Price).
  3. Change the Sorting Builder So he used our special price field (via Sort plugin).

Step 2: Add the custom price field to elasticsearch

We will make a plugin \Magento\Elasticsearch\Model\Adapter\BatchDataMapper\ProductDataMapper::map().

<?php
namespace Vendor\CustomSort\Plugin;

class ProductDataMapperPlugin
{
    public function afterMap(
        \Magento\Elasticsearch\Model\Adapter\BatchDataMapper\ProductDataMapper $subject,
        array $result,
        array $documentData,
        int $storeId,
        array $context = []
    ) {
        // Example: Assume you have dynamic variation prices
        $variationPrices = [
            ['product_id' => 1, 'variation_id' => 1, 'price' => 23.00],
            ['product_id' => 1, 'variation_id' => 2, 'price' => 25.00],
            ['product_id' => 2, 'variation_id' => 1, 'price' => 90.00]
        ];

        foreach ($variationPrices as $variations) {
            $productId = $variations['product_id'];
            $variationId = $variations['variation_id'];
            $price = $variations['price'];
            $result[$productId]['custom_price_b' . $variationId] = $price;
        }

        return $result;
    }
}

This ensures that during indexing, elasticsearch accepts additional fields such as:

{
  "custom_price_b1": 23.00,
  "custom_price_b2": 25.00
}

Step 3: Complete the name of the field for sorting

Magento uses \Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\FieldName\Resolver\Price To complete the price field dynamically.

We will make a plugin for getFieldName() So Magento recognizes our special price field.

<?php
namespace Vendor\CustomSort\Plugin;

class PriceFieldResolverPlugin
{
    public function aroundGetFieldName(
        \Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\FieldName\Resolver\Price $subject,
        callable $proceed,
        AttributeAdapter $attribute,
        $context = []
    ) {
        $options['variation_id'] = 1;
        // Example: Switch to custom price field
        if (isset($options['variation_id'])) {
            $variationId = $options['variation_id'];
            return 'custom_price_b' . $variationId;
        }

        return $proceed($attribute, $context);
    }
}

Now, if we ask for sorting with variation_idMagento will complete the correct special field.

Step 4: Change Sorting Sorters

Magento built such an array \Magento\Elasticsearch\SearchAdapter\Query\Builder\Sort::getSort().
We will add a plugin to put aside this when our custom type is asked.

<?php
namespace Vendor\CustomSort\Plugin;

class SortBuilderPlugin
{
    public function afterGetSort(
        \Magento\Elasticsearch\SearchAdapter\Query\Builder\Sort $subject,
        array $result,
        $sortRequest
    ) {
        if (isset($sortRequest['field']) && $sortRequest['field'] === 'custom_price') {
            $variationId = $sortRequest['variation_id'] ?? 1; // fallback
            $fieldName = 'custom_price_b' . $variationId;

            return [
                [$fieldName => ['order' => $sortRequest['direction'] ?? 'asc']]
            ];
        }

        return $result;
    }
}

In this way, Magento will build elasticsearch questions such as:

"sort": [
  { "custom_price_b1": { "order": "asc" } }
]

Bonus: Handling a lot of prices with painless scripts

What if a product is owned Some custom pricesAnd you want to sort the lowest of them all?
Elasticsearch allows you to use painless script For further sorting.

This is the way you can extend your plugin to restore the minimum price dynamically:

<?php
namespace Vendor\CustomSort\Plugin;

class SortBuilderPlugin
{
    public function afterGetSort(
        \Magento\Elasticsearch\SearchAdapter\Query\Builder\Sort $subject,
        array $result,
        $sortRequest
    ) {
        if (isset($sortRequest['field']) && $sortRequest['field'] === 'custom_price_multi') {
            $order   = $sortRequest['direction'] ?? 'asc';
            $fields  = ['custom_price_b1', 'custom_price_b2', 'custom_price_b3']; // example

            $missing = $order === 'asc' ? 1.0e15 : -1.0e15;

            return [[
                '_script' => [
                    'type'   => 'number',
                    'order'  => $order,
                    'script' => [
                        'lang'   => 'painless',
                        'params' => [
                            'fields'  => $fields,
                            'missing' => $missing,
                        ],
                        'source' => <<<PAINLESS
                            double m = params.missing;
                            double best = Double.POSITIVE_INFINITY;
                            boolean found = false;
                            for (String f : params.fields) {
                                if (doc.containsKey(f) && doc[f].size() > 0) {
                                    double v = doc[f].value;
                                    if (v < best) { best = v; }
                                    found = true;
                                }
                            }
                            if (found) { return best; }
                            return m;
                        PAINLESS
                    ],
                ],
            ]];
        }

        return $result;
    }
}

With this script:

  • Elasticsearch sees All special prices for each product.
  • It chooses The lowest price available.
  • The product is then sorted based on the minimum price.

For more details about sorting and elasticsearch scripts, check the official documentation of elasticsearch.

Step 5: Reindex & Test

After applying the plugin, run:

bin/magento setup:upgrade
bin/magento indexer:reindex
bin/magento cache:flush

Now, the sorting is working both for Single special price And Some custom prices With the lowest price option.


News
Berita
News Flash
Blog
Technology
Sports
Sport
Football
Tips
Finance
Berita Terkini
Berita Terbaru
Berita Kekinian
News
Berita Terkini
Olahraga
Pasang Internet Myrepublic
Jasa Import China
Jasa Import Door to Door

Kiriman serupa