PHPackages                             adriballa/symfony-search-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. adriballa/symfony-search-bundle

ActiveSymfony-bundle

adriballa/symfony-search-bundle
===============================

Symfony bundle that provides search functionality.

v1.0.0(10mo ago)111[1 issues](https://github.com/AdriBalla/symfony-search-bundle/issues)proprietaryPHPPHP ^8.4CI passing

Since Jul 15Pushed 10mo ago2 watchersCompare

[ Source](https://github.com/AdriBalla/symfony-search-bundle)[ Packagist](https://packagist.org/packages/adriballa/symfony-search-bundle)[ RSS](/packages/adriballa-symfony-search-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (24)Versions (4)Used By (0)

🔎 Symfony Search Bundle
=======================

[](#-symfony-search-bundle)

[![PHP](https://camo.githubusercontent.com/d282cc3193faee11ee32307d0c4c9d809e8fafa4b3a8c12c6afbf35d4f7ec617/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/d282cc3193faee11ee32307d0c4c9d809e8fafa4b3a8c12c6afbf35d4f7ec617/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d7768697465)[![Symfony](https://camo.githubusercontent.com/dcc425511ba932c7f375d05fbf7ab6d8b9032a4ccd45f839b42f4eebf1546948/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53796d666f6e792d3030303030303f7374796c653d666f722d7468652d6261646765266c6f676f3d53796d666f6e79266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/dcc425511ba932c7f375d05fbf7ab6d8b9032a4ccd45f839b42f4eebf1546948/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53796d666f6e792d3030303030303f7374796c653d666f722d7468652d6261646765266c6f676f3d53796d666f6e79266c6f676f436f6c6f723d7768697465)[![Elasticsearch](https://camo.githubusercontent.com/9b8560a962bb7509c29691b95482aa7ed5b6ba73eb35c01956aec491d75253a2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f656c61737469637365617263682d2532333033373743432e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d656c6173746963736561726368266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/9b8560a962bb7509c29691b95482aa7ed5b6ba73eb35c01956aec491d75253a2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f656c61737469637365617263682d2532333033373743432e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d656c6173746963736561726368266c6f676f436f6c6f723d7768697465)

This Symfony bundle provides a fast and developer-friendly way to create and manage Elasticsearch indexes, populate them with documents, and perform powerful searches — all in just a few minutes.

With minimal setup, you only need to define two PHP classes per index. From there, everything else is handled for you:

- Ready-to-use endpoints for indexing, updating, deleting, and retrieving documents
- A robust search API for querying your data
- Optional usage of provided ClientInterface services to perform these actions programmatically

No prior knowledge of Elasticsearch is required. The bundle acts as a high-level abstraction layer over Elasticsearch, making all interactions seamless and transparent.

Features
--------

[](#features)

- 🔧 Zero-configuration search engine integration
- 🧱 Index definition via two simple PHP classes
- 📦 Automatic route generation for all operations
- 🧪 Built-in validation before indexation
- 🧰 Optional service interfaces (`IndexClientInterface`, `DocumentClientInterface`, `SearchClientInterface`)
- 🔍 Full-text search with filtering, sorting, pagination, and aggregations
- 📉 No Elasticsearch knowledge required — it's fully abstracted
- 🎛️ Easy to implement your own custom filters

Contents
========

[](#contents)

- [Installation](#installation)
- [Creating your index](#creating-your-index)
- [Adding index to Elasticsearch](#adding-index-to-elasticsearch)
- [Indexing a single document](#indexing-a-single-document)
- [Updating a single document](#updating-a-single-document)
- [Indexing multiple documents](#indexing-multiple-documents)
- [Updating multiple documents](#updating-multiple-documents)
- [Getting a document](#getting-a-document)
- [Deleting a document](#deleting-a-document)
- [Search for documents](#search-for-documents)
- [Retrieving Filterable Fields](#retrieving-filterable-fields)
- [Retrieving Sortable Fields](#retrieving-sortable-fields)

Installation
============

[](#installation)

### 1. Require the bundle

[](#1-require-the-bundle)

```
composer require adriballa/symfony-search-bundle
```

### 2. Load Routes

[](#2-load-routes)

Add the following to `config/routes/adriballa.yaml`:

```
adriballa:
  resource:
    path: '@AdriballaSymfonySearchBundle/src/Controller/'
    namespace: Adriballa\SymfonySearchBundle\Controller
  type: attribute
```

3. Connect the bundle to Elasticsearch
--------------------------------------

[](#3-connect-the-bundle-to-elasticsearch)

Create a config file at `config/packages/adriballa_symfony_search.yaml` to provide the `dsn` of your elasticsearch instance.

```
adriballa_symfony_search:
  elastic_dsn: 'https://elastic:elastic@localhost?SSLVerification=1'
```

Creating your index
===================

[](#creating-your-index)

Creating index definition and mapping
-------------------------------------

[](#creating-index-definition-and-mapping)

To define a new index, create two PHP classes that implements these interfaces :

- `IndexDefinitionInterface`: declares metadata (name, scope, limits)
- `IndexMappingInterface`: declares the structure and fields of the index

Index management is fully automated by the Symfony Search bundle.

\*\*Example of a creation of a `users` index.

```
class UsersIndexDefinition implements IndexDefinitionInterface
{
    // The type of your index, will be used for naming and routing
    public static function getIndexType(): string
    {
        return 'users';
    }

    // Settings and mapping of your index
    public function getIndexMapping(): IndexMappingInterface
    {
        return new UsersIndexMapping();
    }

    // Visibility of your index, only public index can be searched
    public function getScope(): ?IndexScope
    {
        return IndexScope::Public;
    }

    // Max pagination limit
    public function getPaginationLimit(): int
    {
        return 10000;
    }
}
```

```
class UsersIndexMapping implements IndexMappingInterface
{
    use DefaultDynamicTemplates;

    // Settings of your index, define the number of replicas, shards and refresh interval
    public function getIndexSettings(): IndexSettings
    {
        return new IndexSettings(2, 1, 15);
    }

    // Define any raw explicit mapping, can remain blank
    public function getExplicitMapping(): array
    {
        return [];
    }

    // Define the mapping of the index with an array of FieldDefinitionInterface
    /**
    * @return FieldDefinitionInterface[]
    */
    public function getFields(): array
    {
        return [
            new KeywordField('id'),
            new SearchableKeywordField('login'),
            new SearchableKeywordField(path: 'role'),
            new SearchableTextField('description'),
            new BooleanField('active', searchable: true),
            new DateField('starting_date', sortable: true),
            new GeoPointField('location'),
            new ObjectField(
                path: 'monitoring',
                properties: [
                    new LongField('ping'),
                    new LongField('score'),
                    new LongField('reviews'),
                ]),
        ];
    }
}
```

Adding index to Elasticsearch
=============================

[](#adding-index-to-elasticsearch)

When your `IndexDefinitionInterface` is ready, you can automatically create your index in Elasticsearch using either the Symfony Search Bundle route or the method of the `IndexClient`.

Via API
-------

[](#via-api)

**Endpoint**: `/indexes`
**Method**: `POST`
**Request Body (`application/json`)**

ParameterTypeRequiredDescription`indexType`stringYesThe type of index to create, as defined in `IndexDefinition``addAlias`booleanNoWhether to assign an alias to the newly created index`deleteExisting`booleanNoWhether to delete any existing index of the same type**Success response**

```
{
  "type": "users",                        // Your indexType as defined in IndexDefinition
  "name": "index-users-20250626092802"    // The actual name of the index in Elasticsearch
}
```

**Error response**

```
{
  "error": "Index definition for type wrong_index_type not found"
}
```

Via PHP
-------

[](#via-php)

You can also use `IndexClientInterface` as a dependency injection in your project and use it to add your index into Elasticsearch.

```
$indexType = 'users'                        // IndexType of your index as set in your IndexDefinitionInterface
$addAlias = true                            // Should this index be set as Alias (optional, usually true)
$deleteExisting = true                      // Should the previous index set as alias be deleted (false by default, usually true)

$indexClient->createIndex($indexType, $addAlias, $deleteExisting);
```

Indexing a single document
==========================

[](#indexing-a-single-document)

Every indexation and updates of document will be passing through a document validation that will detected if the provided data is matching the `IndexDefinitionMapping` that is set for this index.

Via API
-------

[](#via-api-1)

You can index a single document to Elasticsearch using the Symfony Search Bundle API. The body of this `POST` would be the json encoded data of your document.

**Endpoint**: `/indexes/{indexType}/documents/{id}`
**Method**: `POST`
**Request Body (`application/json`)**

ParameterTypeRequiredDescription`id`string (path)YesThe document IDBodyJSONYesJSON object matching the index mapping definition**Success response**

```
{
  "success": true,
  "errors": []
}
```

**Error response**

```
{
  "success": false,
  "errors": {
    "[id]": "This value should be of type string.",
    "[location][lat]": "This field is missing."
  }
}
```

via PHP
-------

[](#via-php-1)

You can also use `DocumentClientInterface` as a dependency injection in your project and use it to index a document in your Elasticsearch index.

```
$index = new Index('users');
$document = new Document(
            'user-1', // id of your document
            [
                'id' => 'user-1'
                'login' => 'user-1@mail.com'
                // ... json encoded data of your document
            ]
        );

$documentClient->indexDocument($index, $document);
```

Indexing a document with the `DocumentClientInterface` will return a `IndexationResponse`.

Updating a single document
==========================

[](#updating-a-single-document)

Every indexation and updates of document will be passing through a document validation that will detected if the provided data is matching the `IndexDefinitionMapping` that is set for this index.

Via API
-------

[](#via-api-2)

You can update a single document to Elasticsearch using the Symfony Search Bundle API. The body of this `POST` would be the json encoded data of your document.

**Endpoint**: `/indexes/{indexType}/documents/{id}`
**Method**: `PUT`
**Request Body (`application/json`)**

ParameterTypeRequiredDescription`id`string (path)YesThe document IDBodyJSONYesJSON object matching the index mapping definition**Success response**

```
{
  "success": true,
  "errors": []
}
```

**Error response**

```
{
  "success": false,
  "errors": {
    "[id]": "This value should be of type string.",
    "[location][lat]": "This field is missing."
  }
}
```

via PHP
-------

[](#via-php-2)

You can also use `DocumentClientInterface` as a dependency injection in your project and use it to update a document in your Elasticsearch index.

```
$index = new Index('users');
$document = new Document(
            'user-1', // id of your document
            [
                'id' => 'user-1'
                'login' => 'user-1@mail.com'
                // ... json encoded data of your document
            ]
        );

$documentClient->updateDocument($index, $document);
```

Indexing a document with the `DocumentClientInterface` will return a `IndexationResponse`.

Indexing multiple documents
===========================

[](#indexing-multiple-documents)

Every indexation and updates of document will be passing through a document validation that will detected if the provided data is matching the `IndexDefinitionMapping` that is set for this index.

Via API
-------

[](#via-api-3)

You can index multiple documents to Elasticsearch using the Symfony Search Bundle API. The body of this `POST` would be an array of the json encoded data of your document.

**Endpoint**: `/indexes/{indexType}/documents/`
**Method**: `POST`
**Request Body (`application/json`)**

ParameterTypeRequiredDescriptionBodyJSONYesAn array of JSON documents matching the index mapping**Response**

```
{
  "total": 20,        // Number of documents to insert
  "failure": 1,       // Number of failures
  "errors": {         // If there are errors, they are listed here (document id serves as key)
    "1001": {
      "[id]": "This value should be of type string."
    }
  }
}
```

via PHP
-------

[](#via-php-3)

You can also use `DocumentClientInterface` as a dependency injection in your project and use it to index a document in your Elasticsearch index.

```
$index = new Index('users');
$document = new Document(
            'user-1', // id of your document
            [
                'id' => 'user-1'
                'login' => 'user-1@mail.com'
                // ... json encoded data of your document
            ]
        );

$documentClient->mIndexDocuments($index, [$document]);
```

Indexing multiple documents with the `DocumentClientInterface` will return a `MultipleIndexationResponse`.

Updating multiple documents
===========================

[](#updating-multiple-documents)

Every indexation and updates of document will be passing through a document validation that will detected if the provided data is matching the `IndexDefinitionMapping` that is set for this index.

Via API
-------

[](#via-api-4)

You can update multiple documents to Elasticsearch using the Symfony Search Bundle API. The body of this `POST` would be the json encoded data of your document.

**Endpoint**: `/indexes/{indexType}/documents`
**Method**: `PUT`
**Request Body (`application/json`)**

ParameterTypeRequiredDescriptionBodyJSONYesAn array of JSON documents matching the index mapping**Response**

```
{
  "total": 20,        // Number of documents to insert
  "failure": 1,       // Number of failures
  "errors": {         // If there are errors, they are listed here (document id serves as key)
    "1001": {
      "[id]": "This value should be of type string."
    }
  }
}
```

Via PHP
-------

[](#via-php-4)

You can also use `DocumentClientInterface` as a dependency injection in your project and use it to update a document in your Elasticsearch index.

```
$index = new Index('users');
$document = new Document(
            'user-1', // id of your document
            [
                'id' => 'user-1'
                'login' => 'user-1@mail.com'
                // ... json encoded data of your document
            ]
        );

$documentClient->mUpdateDocument($index, [$document]);
```

Updating multiple documents with the `DocumentClientInterface` will return a `MultipleIndexationResponse`.

Getting a document
==================

[](#getting-a-document)

Via API
-------

[](#via-api-5)

You can get a document from your Elasticsearch index using the Symfony Search Bundle API.

**Endpoint**: `/indexes/{indexType}/documents/{id}`
**Method**: `GET`

ParameterTypeRequiredDescription`id`string (path)YesThe ID of the document to fetch**Success Response**
The response of this endpoint when successful will be a json encoded version of your document

**Error Response**
If the document or the index is missing, this endpoint will return a `404 Not Found`.

Via PHP
-------

[](#via-php-5)

You can also use `DocumentClientInterface` as a dependency injection in your project and use it to get a document in your Elasticsearch index.

```
$index = new Index('users');
$id = 'user-1';

$document = $documentClient->getDocument($index, $id);
```

The `DocumentClientInterface` will return a `Document` object when fetching a document.

Deleting a document
===================

[](#deleting-a-document)

Via API
-------

[](#via-api-6)

You can delete a document from your Elasticsearch index using the Symfony Search Bundle API.

**Endpoint**: `/indexes/{indexType}/documents/{id}`
**Method**: `DELETE`

**Success Response**
If the document is found and deleted, the status code of the response will be `204 No Content`.

**Error Response**
If the document or the index is missing, this endpoint will return a 404.

Via PHP
-------

[](#via-php-6)

You can also use `DocumentClientInterface` as a dependency injection in your project and use it to get a document in your Elasticsearch index.

```
$index = new Index('users');
$id = 'user-1';

$document = $documentClient->deleteDocument($index, $id); // Returns true if the document is deleted, false otherwise
```

Search for documents
====================

[](#search-for-documents)

You can search documents in a given index using the Symfony Search Bundle API.

Via API
-------

[](#via-api-7)

**Endpoint**: `/indexes/{indexType}/search`
**Method**: `GET`
**Query Parameters**

ParameterTypeRequiredDescription`query`stringNoThe search term or query string`searchFields`arrayNoList of fields to target for full-text search (can be repeated in query)`start`integerNoStarting offset for pagination (default: 0)`size`integerNoNumber of results to return (default: 10)`filtersBy`arrayNoKey-value pairs for filtering documents (field =&gt; value(s))`aggregatesBy`arrayNoFields to aggregate on (for facets, counts, etc.)`sortsBy`arrayNoSort configuration (e.g., field =&gt; ASC/DESC)**Example of query**

```
localhost/indexes/users/search?start=0&sortsBy[]=starting_date DESC&size=10&filtersBy["active"]=true&filtersBy["monitoring.score"]=100..200&aggregatesBy[]=job_title

```

**Success response**

```
{
  "indexType": "users",
  "success": true,
  "start": 0,
  "size": 10,
  "duration": 23,
  "totalHits": 2,
  "hits": [
    {
      "id": "user-1",
      "login": "admin@site.com"
    },
    {
      "id": "user-2",
      "login": "admin2@site.com"
    }
  ],
  "aggregations": {
    "role": {
      "admin": 2,
      "editor": 0
    }
  }
}
```

Via PHP
-------

[](#via-php-7)

You can search documents in a given index using the `SearchClientInterface` as a dependency injection in your project.

```
$index = new Index('users');
$query = 'john.doe@example.com'; // Optional query string

$searchRequest = new SearchRequest(
    index: $index,
    queryString: 'text to search',                  //Optional : query to search for
    range: new Range(0,10),
    fieldsToSearch: ['email', 'name'],              // Optional : Fields to look for the query, every field will be search if not set
    fieldsToFetch: ['email', 'name', 'created_at'], // Optional : fields to return, everything will be return if not set
    aggregations: [                                 // Optional: your AggregationInterface[] objects
        new Aggregation('job_title'),
    ],
    filters: [                                      // Optional: your FilterableInterface[] objects
        new ExactMatch('active',[true]),
    ],
    sorts: [                                         // Optional: Sort objects for ordering
        new Sort('starting_date',SortDirection::DESC)
    ]
);

$response = $searchClient->search($searchRequest);
```

The `search` method of the `SearchClientInterface` returns a `SearchResponse`.

Retrieving Filterable Fields
============================

[](#retrieving-filterable-fields)

You can retrieve the list of fields that are marked as filterable for a given index.

**Endpoint:** /indexes/{indexType}/filters
**Method:** GET

ParameterTypeRequiredDescription`indexType`string (path)YesThe type of the index to inspect**Success response**

```
  [
    "active",
    "monitoring.score",
    "role"
  ]
```

**Error response**

If the index definition is not found, the API will return a `204 No Content`.

Retrieving Sortables Fields
===========================

[](#retrieving-sortables-fields)

You can retrieve the list of fields that are marked as sortable for a given index.

**Endpoint:** /indexes/{indexType}/sorts
**Method:** GET

ParameterTypeRequiredDescription`indexType`string (path)YesThe type of the index to inspect**Success response**

```
  [
    "starting_date",
    "monitoring.score"
  ]
```

**Error response**

If the index definition is not found, the API will return a `204 No Content`.

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance53

Moderate activity, may be stable

Popularity8

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

300d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ead25a338290b9800b289a6d30044d530d3c50727021bbe0121491eda8b6e559?d=identicon)[AdriBalla](/maintainers/AdriBalla)

---

Top Contributors

[![AdriBalla](https://avatars.githubusercontent.com/u/25460292?v=4)](https://github.com/AdriBalla "AdriBalla (3 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/adriballa-symfony-search-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/adriballa-symfony-search-bundle/health.svg)](https://phpackages.com/packages/adriballa-symfony-search-bundle)
```

###  Alternatives

[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[easycorp/easyadmin-demo

EasyAdmin Demo Application

145.7k](/packages/easycorp-easyadmin-demo)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[kadirov/api-starter-kit

443.9k](/packages/kadirov-api-starter-kit)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[kimai/kimai

Kimai - Time Tracking

4.6k7.4k1](/packages/kimai-kimai)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
