Skip to main content

Documentation Index

Fetch the complete documentation index at: https://algolia.com/llms.txt

Use this file to discover all available pages before exploring further.

Indexing data

You have to define the entities that should be indexed to Algolia. You can do this by adding the entities to your configuration file, under the algolia_search.indices key. Each entry under the indices key must contain the following attributes:
  • name is the canonical name of the index in Algolia
  • class is the full class reference of the entity to index
For example, to index all posts:
YAML
algolia_search:
  indices:
    - name: posts
      class: App\Entity\Post

enable_serializer_groups

Before sending your data to Algolia, each entity is converted to an array using the Symfony built-in serializer. This option lets you define which attributes to index using the #[Groups(['searchable'])] attribute. For more information, see Normalizers. Example:
YAML
algolia_search:
  indices:
    - name: posts
      class: App\Entity\Post
      enable_serializer_groups: true
For more information about sending data to Algolia, see Index data into Algolia.

Batching

By default, calls to Algolia for indexing or removing data are batched per 500 items. You can modify the batch size in your configuration.
YAML
algolia_search:
  batchSize: 250
The import command also uses this parameter to retrieve data with Doctrine. If you run out of memory while importing your data, use a smaller batchSize value.

JMS serializer

The bundle also provides basic support for the JMS serializer. Note that not all features are supported (like the #[Groups] attribute). In your configuration, pass the name of the JMS serializer service (jms_serializer by default).
YAML
algolia_search:
  serializer: jms_serializer
  indices:
    - name: posts
      class: App\Entity\Post

Normalizers

By default all entities are converted to an array with the built-in Symfony normalizers (for example GetSetMethodNormalizer, DateTimeNormalizer, or ObjectNormalizer) which should be enough for simple use cases. For more control over what you send to Algolia, or to avoid circular references, write your own normalizer. Symfony uses the first normalizer in the array to support your entity or format. You can change the order in your service declaration.
The normalizer is called with searchableArray format.
You have many choices on how to customize your records:
The following features are only supported with the default Symfony serializer, not with JMS serializer.

Attributes

The simplest way to choose which fields to index is to mark them with the #[Groups] attribute. This feature relies on the built-in ObjectNormalizer and its serializer-group support.
Attributes require enable_serializer_groups to be set to true in the configuration.
PHP
<?php

namespace App\Entity;

use Symfony\Component\Serializer\Attribute\Groups;

class Post
{
    // ... other properties and methods ...

    #[Groups(['searchable'])]
    public function getTitle(): ?string
    {
        return $this->title;
    }

    #[Groups(['searchable'])]
    public function getSlug(): ?string
    {
        return $this->slug;
    }

    #[Groups(['searchable'])]
    public function getCommentCount(): ?int
    {
        return count($this->comments);
    }
}

Normalize

Another option is to implement a dedicated method that returns the entity as an array. This feature relies on the CustomNormalizer that ships with the serializer component. Implement the Symfony\Component\Serializer\Normalizer\NormalizableInterface interface and write your normalize method. Example based on a simplified version of this Post entity:
PHP
<?php

namespace App\Entity;

use Symfony\Component\Serializer\Normalizer\NormalizableInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class Post implements NormalizableInterface
{
    public function normalize(NormalizerInterface $serializer, $format = null, array $context = []): array
    {
        return [
            'title' => $this->getTitle(),
            'content' => $this->getContent(),
            'comment_count' => $this->getComments()->count(),
            'tags' => array_unique(array_map(function ($tag) {
              return $tag->getName();
            }, $this->getTags()->toArray())),

            // Reuse the $serializer
            'author' => $serializer->normalize($this->getAuthor(), $format, $context),
            'published_at' => $serializer->normalize($this->getPublishedAt(), $format, $context),
        ];
    }
}

Handle multiple formats

In case you are already using this method for something else, like encoding entities into JSON for instance, you may want to use a different format for both use cases. You can rely on the format to return different arrays.
PHP
public function normalize(NormalizerInterface $serializer, $format = null, array $context = []): array
{
    if (\Algolia\SearchBundle\Searchable::NORMALIZATION_FORMAT === $format) {
        return [
            'title' => $this->getTitle(),
            'content' => $this->getContent(),
            'author' => $this->getAuthor()->getFullName(),
        ];
    }

    // Or if it's not for search
    return ['title' => $this->getTitle()];
}

Custom normalizers

You can create a custom normalizer for any entity by implementing the Symfony\Component\Serializer\Normalizer\NormalizerInterface interface. The following snippet shows a simple UserNormalizer.
PHP
<?php
// src/Serializer/Normalizer/UserNormalizer.php

namespace App\Serializer\Normalizer;

use Algolia\SearchBundle\Searchable;
use App\Entity\User;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class UserNormalizer implements NormalizerInterface
{
    public function normalize($object, ?string $format = null, array $context = []): array
    {
        return [
            'id'       => $object->getId(),
            'username' => $object->getUsername(),
        ];
    }

    public function supportsNormalization($data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof User;

        // Or if you want to use it only for indexing:
        // return $data instanceof User && Searchable::NORMALIZATION_FORMAT === $format;
    }

    public function getSupportedTypes(?string $format): array
    {
        return [User::class => true];
    }
}
Tag the normalizer to add it to the default serializer. In your service declaration, add the following.
services:
  user_normalizer:
    class: App\Serializer\Normalizer\UserNormalizer
    tags:
      - { name: serializer.normalizer }
With this configuration, the serializer uses UserNormalizer whenever it encounters a User — either as the top-level indexed entity or as a nested property on another entity being indexed.

Order of normalizers

Because Symfony uses the first normalizer that supports your entity or format, the order is important. The ObjectNormalizer is registered with a priority of -1000 and should always be the last fallback. Most of Symfony’s built-in normalizers sit in the negative range below the CustomNormalizer (registered at -800), though a few (such as the UnwrappingDenormalizer) run at higher priorities. To keep your normalizers ahead of the bundle’s CustomNormalizer, register them above -800. This also puts them ahead of the lower-priority Symfony fallback normalizers, such as ObjectNormalizer. The default priority is 0. You can change the priority in your service definition.
services:
  serializer.normalizer.datetime:
    class: Symfony\Component\Serializer\Normalizer\DateTimeNormalizer
    tags:
      - { name: serializer.normalizer, priority: -100 }
Last modified on April 27, 2026