ACSEOTypesenseBundle
This bundle provides integration with Typesense with Symfony.
It relies on the official TypeSense PHP package
Features include:
- Doctrine object transformer to Typesense indexable data
- Usefull services to search in collections
- Listeners for Doctrine events for automatic indexing
Installation
Install the bundle using composer
composer require acseo/typesense-bundle
Enable the bundle in you Symfony project
<?php
return [
ACSEO\TypesenseBundle\ACSEOTypesenseBundle::class => ['all' => true],
Configuration
Configure the Bundle
# .env
TYPESENSE_URL=http://localhost:8108
TYPESENSE_KEY=123
acseo_typesense:
typesense:
url: '%env(resolve:TYPESENSE_URL)%'
key: '%env(resolve:TYPESENSE_KEY)%'
collection_prefix: 'test_'
collections:
books:
entity: 'App\Entity\Book'
fields:
id:
name: id
type: primary
sortable_id:
entity_attribute: id
name: sortable_id
type: int32
title:
name: title
type: string
description:
name: title
type: description
author:
name: author
type: object
author.country:
name: author_country
type: string
facet: true
entity_attribute: author.country
genres:
name: genres
type: collection
publishedAt:
name: publishedAt
type: datetime
optional: true
cover_image_url:
name: cover_image_url
type: string
optional: true
entity_attribute: ACSEO\Service\BookConverter::getCoverImageURL
embeddings:
name: embeddings
type: float[]
embed:
from:
- title
- description
model_config:
model_name: ts/e5-small
default_sorting_field: sortable_id
symbols_to_index: ['+']
users:
entity: App\Entity\User
fields:
id:
name: id
type: primary
sortable_id:
entity_attribute: id
name: sortable_id
type: int32
email:
name: email
type: string
default_sorting_field: sortable_id
token_separators: ['+', '-', '@', '.']
You can use basic types supported by Typesense for your fields : string, int32, float, etc.
You can also use specific type names, such as : primary, collection, object
Data conversion from Doctrine entity to Typesense data is managed by ACSEO\TypesenseBundle\Transformer\DoctrineToTypesenseTransformer
Usage
Create index and populate data
This bundle comes with useful commands in order to create and index your data
php bin/console typesense:create
php bin/console typesense:import
Search documents
This bundle creates dynamic generic finders services that allows you to query Typesense
The finder services are named like this : typesense.finder.collection_name
You can inject the generic finder in your Controller or into other services.
You can also create specific finder for a collection. See documentation below.
services:
App\Controller\BookController:
arguments:
$bookFinder: '@typesense.finder.books'
<?php
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use ACSEO\TypesenseBundle\Finder\TypesenseQuery;
class BookController extends AbstractController
{
private $bookFinder;
public function __construct($bookFinder)
{
$this->bookFinder = $bookFinder;
}
public function search()
{
$query = new TypesenseQuery('Jules Vernes', 'author');
$results = $this->bookFinder->query($query)->getResults();
$rawResults = $this->bookFinder->rawQuery($query)->getResults();
}
Querying Typesense
The class TypesenseQuery() class takes 2 arguments :
- The search terme (
q)
- The fields to search on (
queryBy)
You can create more complex queries using all the possible Typsense search arguments
<?php
use ACSEO\TypesenseBundle\Finder\TypesenseQuery;
$simpleQuery = new TypesenseQuery('search term', 'collection field to search in');
$complexQuery = new TypesenseQuery('search term', 'collection field to search in')
->filterBy('theme: [adventure, thriller]')
->addParameter('key', 'value')
->sortBy('year:desc');
Create specific finder for a collection
You can easily create specific finders for each collection that you declare.
acseo_typesense:
collections:
books:
finders:
books_autocomplete:
finder_parameters:
query_by: title
limit: 10
prefix: true
num_typos: 1
drop_tokens_threshold: 1
This configuration will create a service named @typesense.specificfinder.books.books_autocomplete.
You can inject the specific finder in your Controller or into other services
services:
App\Controller\BookController:
arguments:
$autocompleteBookFinder: '@typesense.specificfinder.books.books_autocomplete'
and then use it like this :
<?php
class BookController extends AbstractController
{
private $autocompleteBookFinder;
public function __construct($autocompleteBookFinder)
{
$this->autocompleteBookFinder = $autocompleteBookFinder;
}
public function autocomplete($term = '')
{
$results = $this->autocompleteBookFinder->search($term)->getResults();
$rawResults = $this->autocompleteBookFinder->search($term)->getRawResults();
}
Use different kind of services
This bundles creates different services that you can use in your Controllers or anywhere you want.
typesense.client : the basic client inherited from the official typesense-php package
typesense.collection_client : this service allows you to do basic actions on collections, and allows to perform search and multisearch action.
typesense.finder.* : this generated service allows you to perform query or rawQuery on a specific collection. Example of a generated service : typesense.finder.candidates
typesense.specificfinder.*.* : this generated service allows you to run pre-configured requests (declared in : config/packages/acseo_typesense.yml). Example of a generated service : typesense.specificfinder.candidates.default
Note : there a other services. You can use the debug:container command in order to see all of them.
Doctrine Listeners
Doctrine listeners will update Typesense with Entity data during the following events :
- postPersist
- postUpdate
- preDelete
Perform multisearch
You can create multisearch requests and get results using the collectionClient service.
$searchRequests = [
(new TypesenseQuery('Jules'))->addParameter('collection', 'author'),
(new TypesenseQuery('Paris'))->addParameter('collection', 'library')
];
$commonParams = new TypesenseQuery()->addParameter('query_by', 'name');
$response = $this->collectionClient->multisearch($searchRequests, $commonParams);
Cookbook
Testing the Bundle
tests are written in the tests directory.
- Unit tests doesn't require a running Typesense server
- Functional tests require a running Typesense server
You can launch the tests with the following commands :
$ php ./vendor/bin/phpunit tests/Unit
$ composer run-script typesenseServer
$ php ./vendor/bin/phpunit tests/Functional