Guide

Create a Custom Elasticsearch Filter

elasticsearch

Elasticsearch filters have access to the context created from the HTTP request and to the Elasticsearch query clause. They are only applied to collections. If you want to deal with the query DSL through the search request body, extensions are the way to go. Existing Elasticsearch filters are applied through a constant score query. A constant score query filter is basically a class implementing the ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface and the ApiPlatform\Elasticsearch\Filter\FilterInterface. API Platform includes a convenient abstract class implementing this last interface and providing utility methods: ApiPlatform\Elasticsearch\Filter\AbstractFilter. Suppose you want to use the match filter on a property named $title and you want to add the and operator to your query:

// src/App/ElasticSearch.php
namespace App\ElasticSearch;
use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface;
use ApiPlatform\Metadata\Operation;
/*
 * Thanks to Symfony autowiring and autoconfiguration, this extension is automatically declared as a service.
 */
final class AndOperatorFilterExtension implements RequestBodySearchCollectionExtensionInterface
{
    public function applyToCollection(array $requestBody, string $resourceClass, ?Operation $operation = null, array $context = []): array
    {
        $requestBody['query'] = $requestBody['query'] ?? [];
        $requestBody['query']['constant_score']['filter']['bool']['must'][0]['match']['title'] = [
            'query' => $context['filters']['title'],
            'operator' => 'and',
        ];
        return $requestBody;
    }
}
// src/App/ElasticSearch.php
namespace App\ElasticSearch;
use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface;
use ApiPlatform\Metadata\Operation;
/*
 * Thanks to Symfony autowiring and autoconfiguration, this extension is automatically declared as a service.
 */
final class AndOperatorFilterExtension implements RequestBodySearchCollectionExtensionInterface
{
    public function applyToCollection(array $requestBody, string $resourceClass, ?Operation $operation = null, array $context = []): array
    {
        $requestBody['query'] = $requestBody['query'] ?? [];
        $requestBody['query']['constant_score']['filter']['bool']['must'][0]['match']['title'] = [
            'query' => $context['filters']['title'],
            'operator' => 'and',
        ];
        return $requestBody;
    }
}

Copyright © 2023 Kévin Dunglas

Sponsored by Les-Tilleuls.coop