PHPackages                             nramos/search-indexer - 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. [Database &amp; ORM](/categories/database)
4. /
5. nramos/search-indexer

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

nramos/search-indexer
=====================

A Doctrine entity indexer supporting Meilisearch and extensible for other indexing systems.

2.2.7(2mo ago)33.1k↑40.5%1MITPHPPHP &gt;=8.2CI failing

Since Jul 1Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/n-ramos/search-indexer)[ Packagist](https://packagist.org/packages/nramos/search-indexer)[ Docs](https://github.com/n-ramos/search-indexer)[ RSS](/packages/nramos-search-indexer/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (13)Versions (33)Used By (0)

[![codecov](https://camo.githubusercontent.com/9c71091cc83dd64e480d28c98b263358e4295d87a254d1e5ad7239412e2677db/68747470733a2f2f636f6465636f762e696f2f67682f6e2d72616d6f732f7365617263682d696e64657865722f6272616e63682f6d61696e2f67726170682f62616467652e7376673f746f6b656e3d565a4f51324336535451)](https://codecov.io/gh/n-ramos/search-indexer)🌍 Documentation

This documentation is available in:

#### 🇬🇧 English

[](#-english)

#### 🇫🇷 Français

[](#-français)

🇫🇷 Français
===========

[](#-français-1)

Le package `nramos/search-indexer` permet d'indexer des entités Doctrine sur différents systèmes d'indexation via des annotations. Actuellement, un adaptateur pour Meilisearch est disponible, mais la structure permet d'ajouter d'autres systèmes d'indexation à l'avenir.

Installation
------------

[](#installation)

Installez le package via Composer :

```
composer require nramos/search-indexer
```

Configuration
-------------

[](#configuration)

### Déclarer le service dans services.yaml:

[](#déclarer-le-service-dans-servicesyaml)

Exemple pour Meilisearch:

```
parameters:
    meilisearch_default_host: "localhost:7700"
    empty: ""
    meilisearch_key:    '%env(default:empty:MEILISEARCH_KEY)%'
    meilisearch_host:   '%env(default:meilisearch_default_host:MEILISEARCH_HOST)%'
services:
  ...
 Nramos\SearchIndexer\Indexer\SearchClientInterface:
  class: Nramos\SearchIndexer\Meilisearch\MeilisearchClient
  bind:
   $host: '%meilisearch_host%'
   $apiKey: '%meilisearch_key%'
```

### Déclarer l'index sur une entité

[](#déclarer-lindex-sur-une-entité)

Utilisez l'annotation `#[SearchIndex]` sur une classe pour définir un index. Par exemple :

```
#[SearchIndex(indexName: 'biens', autoIndex: true)]
```

- **indexName** : le nom de l'index sur le système d'indexation.
- **autoIndex** : définit si les entités doivent être automatiquement indexées lors des insertions et des mises à jour. Si false, vous devrez gérer l'indexation manuellement.

### Configurer les propriétés à indexer

[](#configurer-les-propriétés-à-indexer)

Utilisez l'annotation `#[SearchProperty]` sur les propriétés de l'entité pour définir comment celles-ci seront indexées :

```
#[SearchProperty(propertyName: 'typeBien', relationProperties: [], filterable: true, sortable: true, searchable: true)]
```

Il faut obligatoirement ajouter une clé primaire à l'indexer :

```
#[SearchProperty(propertyName: 'id', isPk:true, relationProperties: [], filterable: true, sortable: true, searchable: true)]
```

### Configurer les propriétés à indexer

[](#configurer-les-propriétés-à-indexer-1)

- propertyName : nom de la propriété à indexer.
- filterable : si la propriété peut être utilisée dans les filtres de recherche.
- sortable : si la propriété peut être utilisée pour trier les résultats.
- searchable : si la propriété peut être utilisée dans la recherche textuelle. -relationProperties : spécifie les clés à extraire dans le cas d'une relation (par ex. ManyToMany).

### Gérer les relations

[](#gérer-les-relations)

Lorsque vous avez des relations comme ManyToMany, vous pouvez spécifier des relationProperties pour indexer des valeurs provenant de la relation. Par exemple :

```
#[ORM\ManyToMany(targetEntity: Heating::class, mappedBy: 'houses')]
#[SearchProperty(propertyName: 'heatings', relationProperties: ['name'], filterable: true)]
private Collection $heatings;
```

Dans cet exemple, la propriété name des entités liées à Heating sera indexée sous le nom `heatings`.

### Désactiver l'auto-indexation

[](#désactiver-lauto-indexation)

Si vous ne souhaitez pas utiliser l'indexation automatique fournie par le package, vous pouvez désactiver l'auto-indexation en définissant `autoIndex: false` dans l'annotation `#[SearchIndex]` et en créant un subscriber personnalisé pour gérer l'indexation.

Utilisation des filtres de recherche
------------------------------------

[](#utilisation-des-filtres-de-recherche)

Le package propose une interface SearchFilterInterface pour faciliter la création de requêtes complexes. Un adaptateur pour Meilisearch est disponible par défaut. Voici un exemple d'utilisation avec Meilisearch :

```
$filter = (new MeiliSearchFilter())
    ->addFilter('status', '=', 'active')
    ->addFilter('rating.users', '>', 85)
    ->openParenthesis()
    ->addFilter('genres', '=', 'horror', 'OR')
    ->addFilter('genres', '=', 'comedy')
    ->closeParenthesis()
    ->openParenthesis()
    ->addFilter('genres', '=', 'horror')
    ->addFilter('genres', '=', 'comedy')
    ->closeParenthesis()
    ->addInFilter('role', ['admin', 'user'])
    ->addLocationFilter('radius', 48.8566, 2.3522, 5, 'km')
    ->addLocationBounding('bounding', [48.8566, 2.3522, 49.8566, 2.4522], 'km')
    ->addExistenceFilter('release_date')
    ->addExistenceFilter('overview', false);
```

### Exécution de la recherche

[](#exécution-de-la-recherche)

Pour exécuter la recherche, vous devez implémenter l'interface SearchClientInterface. Un client Meilisearch est fourni par le package sous la classe `MeilisearchClient`. Voici un exemple :

```
$results = $client->search(
    'houses', // Nom de l'index
    'search query', // Requête de recherche
    $filter, // Filtre de recherche
    10, // Limite
    1, // Page
    ['status', 'genres'] // Facettes
);
```

Exemple d'entité
----------------

[](#exemple-dentité)

Voici un exemple d'entité avec les annotations pour l'indexation :

```
namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Nramos\SearchIndexer\Annotation\SearchIndex;
use Nramos\SearchIndexer\Annotation\SearchProperty;
use Nramos\SearchIndexer\Indexer\IndexableEntityInterface;

#[ORM\Entity]
#[ORM\Table(name: 'houses')]
#[SearchIndex(indexName: 'houses', autoIndex: true)]
class House implements IndexableEntityInterface
{
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    #[ORM\Column(type: 'integer')]
    #[SearchProperty(propertyName: 'id',isPk: true, filterable: true, sortable: false)]

    private $id;

    #[ORM\Column(type: 'string')]
    #[SearchProperty(propertyName: 'name', filterable: true, sortable: false)]
    private ?string $name = null;

    #[ORM\Column(type: 'integer')]
    #[SearchProperty(propertyName: 'price', filterable: false, sortable: true)]
    private $price;

    #[ORM\ManyToOne(targetEntity: HouseType::class)]
    #[ORM\JoinColumn(name: 'house_type_id', referencedColumnName: 'id')]
    #[SearchProperty(propertyName: 'type', relationProperties: ['typeName'], filterable: true, sortable: false)]
    private $houseType;

    #[ORM\ManyToMany(targetEntity: Heating::class, mappedBy: 'houses')]
    #[SearchProperty(propertyName: 'heatings', relationProperties: ['name'], filterable: true)]
    private Collection $heatings;

    public function __construct()
    {
        $this->heatings = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getPrice(): mixed
    {
        return $this->price;
    }

    public function setPrice(mixed $price): void
    {
        $this->price = $price;
    }
    #[SearchProperty(propertyName: 'houseTypeFormated', filterable: true, sortable: false)]
    public function getHouseTypeFormated(): mixed
    {
        return $this->houseType " - de 50 m²";
    }
    public function getHouseType(): mixed
    {
        return $this->houseType;
    }

    public function setHouseType(mixed $houseType): void
    {
        $this->houseType = $houseType;
    }

    public function setId(mixed $id): void
    {
        $this->id = $id;
    }
}
```

Aller plus loin
---------------

[](#aller-plus-loin)

### Créer un subscriber personnalisé

[](#créer-un-subscriber-personnalisé)

Pour gérer l'indexation manuellement, vous pouvez créer un subscriber personnalisé pour écouter les événements Doctrine et appeler l'indexation manuellement. Voici un exemple implémenté globalement :

```
#[SearchIndex(indexName: 'houses', autoIndex: false)]
```

```
