ElasticSearch v6.0 deprecated multiple types in one index. You can read more here: Removal of mapping types

How to deal with this breaking change?

Create MultiIndex.php file in your Symfony App project


<?php

declare(strict_types=1);

/*
 * Created by Exploit.cz <insekticid AT exploit.cz>
 */

namespace App\Search\Elastica;

use Elastica\Exception\InvalidException;
use Elastica\Index;
use Elastica\ResultSet\BuilderInterface;
use Elastica\Search;

class MultiIndex extends Index
{
    /**
     * Array of indices.
     *
     * @var array
     */
    protected $_indices = [];

    /**
     * Adds a index to the list.
     *
     * @param \Elastica\Index|string $index Index object or string
     *
     * @throws \Elastica\Exception\InvalidException
     *
     * @return $this
     */
    public function addIndex($index)
    {
        if ($index instanceof Index) {
            $index = $index->getName();
        }

        if (!is_scalar($index)) {
            throw new InvalidException('Invalid param type');
        }

        $this->_indices[] = (string) $index;

        return $this;
    }

    /**
     * Add array of indices at once.
     *
     * @param array $indices
     *
     * @return $this
     */
    public function addIndices(array $indices = [])
    {
        foreach ($indices as $index) {
            $this->addIndex($index);
        }

        return $this;
    }

    /**
     * Return array of indices.
     *
     * @return array List of index names
     */
    public function getIndices()
    {
        return $this->_indices;
    }

    /**
     * @param string|array|\Elastica\Query $query
     * @param int|array                    $options
     * @param BuilderInterface             $builder
     *
     * @return Search
     */
    public function createSearch($query = '', $options = null, BuilderInterface $builder = null)
    {
        $search = new Search($this->getClient(), $builder);
        //$search->addIndex($this);
        $search->addIndices($this->getIndices());
        $search->setOptionsAndQuery($options, $query);

        return $search;
    }
}

Refactor fos_elastica.yaml and move all types from the same index to your newly created index (separate it).

Example:

  • before: index:recipes, types: [recipe, recipes]
  • after:
    • index: recipe, type: recipe
    • index: recipes, type: recipes

Now add MultiIndex service into services.yaml file in config directory and change recipe and recipes to your newly created index names.

    App\Search\Elastica\MultiIndex:
        arguments:
            $name: 'recipe'
        calls:
            - [ addIndices, [['@fos_elastica.index.recipe', '@fos_elastica.index.recipes']]]

    Elastica\SearchableInterface: '@App\Search\Elastica\MultiIndex'

    FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection:
        arguments:
            - {
                recipe: '@fos_elastica.elastica_to_model_transformer.recipe.recipe',
                recipes: '@fos_elastica.elastica_to_model_transformer.recipes.recipes'
              }

    FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface: '@FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection'

    FOS\ElasticaBundle\Finder\TransformedFinder: ~
        #arguments:
        #    - '@App\Search\Elastica\MultiIndex'
        #    - '@FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection'

    FOS\ElasticaBundle\Finder\PaginatedFinderInterface: '@FOS\ElasticaBundle\Finder\TransformedFinder'

Now create SearchRepository.php

<?php

declare(strict_types=1);

use Elastica\Query\Match;
use FOS\ElasticaBundle\Repository;

class SearchRepository extends Repository
{
    public function search(string $searchTerm, int $page = 1, int $limit = 48) : ?array
    {
        if ($searchTerm) {
            $fieldQuery = new Match();
            $fieldQuery->setFieldQuery('name', $searchTerm);
            $items     = $this->findPaginated($fieldQuery);
            $items->setMaxPerPage($limit);
            $items->setCurrentPage($page);

            return $items;
        }

        return null;
    }
}

Now you can use this repository in your Controller

<?php

declare(strict_types=1);

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Repository\SearchRepository;

class SearchController extends AbstractController
{
    /**
     * @var SearchRepository
     */
    protected $searchRepository;

    public function __construct(SearchRepository $searchRepository)
    {
        $this->searchRepository = $searchRepository;
    }
}

Github issues Multiple index paginated search #1521, Multi type search to multi index search #1385