{"id":19003466,"url":"https://github.com/acseo/typesensebundle","last_synced_at":"2025-04-09T08:04:03.367Z","repository":{"id":44098461,"uuid":"260014069","full_name":"acseo/TypesenseBundle","owner":"acseo","description":"Typesense PHP integration for your Symfony project","archived":false,"fork":false,"pushed_at":"2025-01-20T22:49:33.000Z","size":190,"stargazers_count":63,"open_issues_count":19,"forks_count":38,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-02T06:40:56.549Z","etag":null,"topics":["symfony","symfony-bundle","typesense"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/acseo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-29T18:47:53.000Z","updated_at":"2025-02-11T07:40:10.000Z","dependencies_parsed_at":"2023-11-13T15:25:46.128Z","dependency_job_id":"b0c0f659-f5d2-4faa-934c-7c01c097ec75","html_url":"https://github.com/acseo/TypesenseBundle","commit_stats":{"total_commits":122,"total_committers":10,"mean_commits":12.2,"dds":0.3688524590163934,"last_synced_commit":"e98fc86788b426cded649d9388033e3771a1abb2"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acseo%2FTypesenseBundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acseo%2FTypesenseBundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acseo%2FTypesenseBundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acseo%2FTypesenseBundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/acseo","download_url":"https://codeload.github.com/acseo/TypesenseBundle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247999859,"owners_count":21031046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["symfony","symfony-bundle","typesense"],"created_at":"2024-11-08T18:19:11.450Z","updated_at":"2025-04-09T08:04:03.349Z","avatar_url":"https://github.com/acseo.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ACSEOTypesenseBundle\n\nThis bundle provides integration with [Typesense](https://typesense.org/) with Symfony. \n\nIt relies on the official [TypeSense PHP](https://github.com/typesense/typesense-php) package\n\nFeatures include:\n\n- Doctrine object transformer to Typesense indexable data\n- Usefull services to search in collections \n- Listeners for Doctrine events for automatic indexing\n\n## Installation\n\nInstall the bundle using composer \n\n```bash\ncomposer require acseo/typesense-bundle\n````\n\nEnable the bundle in you Symfony project\n\n```php\n\n\u003c?php\n// config/bundles.php\n\nreturn [\n    ACSEO\\TypesenseBundle\\ACSEOTypesenseBundle::class =\u003e ['all' =\u003e true],\n```\n\n## Configuration\n\nConfigure the Bundle\n\n```\n# .env\nTYPESENSE_URL=http://localhost:8108\nTYPESENSE_KEY=123\n```\n\n```yaml\n# config/packages/acseo_typesense.yml\nacseo_typesense:\n    # Typesense host settings\n    typesense:\n        url: '%env(resolve:TYPESENSE_URL)%'\n        key: '%env(resolve:TYPESENSE_KEY)%'\n        collection_prefix: 'test_'                 # Optional : add prefix to all collection \n                                                   #            names in Typesense\n    # Collection settings\n    collections:\n        books:                                     # Typesense collection name\n            entity: 'App\\Entity\\Book'              # Doctrine Entity class\n            fields: \n                #\n                # Keeping Database and Typesense synchronized with ids\n                #\n                id:                                # Entity attribute name\n                    name: id                       # Typesense attribute name\n                    type: primary                  # Attribute type\n                #\n                # Using again id as a sortable field (int32 required)\n                #\n                sortable_id:\n                    entity_attribute: id             # Entity attribute name forced\n                    name: sortable_id                # Typesense field name\n                    type: int32\n                title: \n                    name: title\n                    type: string\n                description: \n                    name: title\n                    type: description                    \n                author:\n                     name: author\n                     type: object                    # Object conversion with __toString()\n                author.country:\n                    name: author_country           \n                    type: string\n                    facet: true                      # Declare field as facet (required to use \"group_by\" query option)\n                    entity_attribute: author.country # Equivalent of $book-\u003egetAuthor()-\u003egetCountry()\n                genres:\n                    name: genres\n                    type: collection                 # Convert ArrayCollection to array of strings\n                publishedAt: \n                    name: publishedAt\n                    type: datetime\n                    optional: true                   # Declare field as optional\n                cover_image_url:\n                    name: cover_image_url\n                    type: string\n                    optional: true\n                    entity_attribute: ACSEO\\Service\\BookConverter::getCoverImageURL # use a service converter instead of an attribute\n                embeddings:                          # Since Typesense 0.25, you can generate Embeddings on the fly\n                    name: embeddings                 # and retrieve your documents using an vectorial search\n                    type: float[]                    # more info : https://typesense.org/docs/27.0/api/vector-search.html\n                    embed:\n                        from:\n                            - title\n                            - description\n                        model_config: \n                            model_name: ts/e5-small\n            default_sorting_field: sortable_id       # Default sorting field. Must be int32 or float\n            symbols_to_index: ['+']                  # Optional - You can add + to this list to make the word c++ indexable verbatim.\n        users:\n            entity: App\\Entity\\User\n            fields:\n                id:\n                    name: id\n                    type: primary\n                sortable_id:\n                    entity_attribute: id\n                    name: sortable_id\n                    type: int32\n                email:\n                    name: email\n                    type: string\n            default_sorting_field: sortable_id\n            token_separators: ['+', '-', '@', '.']  # Optional - This will cause contact+docs-example@typesense.org to be indexed as contact, docs, example, typesense and org.\n```\n\nYou can use basic types supported by Typesense for your fields : string, int32, float, etc.\nYou can also use specific type names, such as : primary, collection, object\n\nData conversion from Doctrine entity to Typesense data is managed by `ACSEO\\TypesenseBundle\\Transformer\\DoctrineToTypesenseTransformer`\n\n## Usage\n\n### Create index and populate data\n\nThis bundle comes with useful commands in order to create and index your data\n\n```yaml\n# Creation collections structure\nphp bin/console typesense:create\n\n# Import collections with Doctrine entities\nphp bin/console typesense:import\n```\n\n### Search documents\n\nThis bundle creates dynamic generic **finders** services that allows you to query Typesense\n\nThe finder services are named like this  : typesense.finder.*collection_name*\n\nYou can inject the generic finder in your Controller or into other services. \n\nYou can also create specific finder for a collection. See documentation below.\n\n```yaml\n# config/services.yaml\nservices:\n    App\\Controller\\BookController:\n        arguments:\n            $bookFinder: '@typesense.finder.books'    \n```\n\n```php\n\u003c?php\n\n// src/Controller/BookController.php\n\nuse Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController;\nuse ACSEO\\TypesenseBundle\\Finder\\TypesenseQuery;\n\n//\nclass BookController extends AbstractController\n{\n    private $bookFinder;\n\n    public function __construct($bookFinder)\n    {\n        $this-\u003ebookFinder = $bookFinder;\n    }\n\n    public function search()\n    {\n        $query = new TypesenseQuery('Jules Vernes', 'author');\n\n        // Get Doctrine Hydrated objects\n        $results = $this-\u003ebookFinder-\u003equery($query)-\u003egetResults();\n        \n        // dump($results)\n        // array:2 [▼\n        //    0 =\u003e App\\Entity\\Book {#522 ▶}\n        //    1 =\u003e App\\Entity\\Book {#525 ▶}\n        //]\n        \n        // Get raw results from Typesence\n        $rawResults = $this-\u003ebookFinder-\u003erawQuery($query)-\u003egetResults();\n        \n        // dump($rawResults)\n        // array:2 [▼\n        //    0 =\u003e array:3 [▼\n        //        \"document\" =\u003e array:4 [▼\n        //        \"author\" =\u003e \"Jules Vernes\"\n        //        \"id\" =\u003e \"100\"\n        //        \"published_at\" =\u003e 1443744000\n        //        \"title\" =\u003e \"Voyage au centre de la Terre \"\n        //       ]\n        //       \"highlights\" =\u003e array:1 [▶]\n        //       \"seq_id\" =\u003e 4\n        //    ]\n        //    1 =\u003e array:3 [▼\n        //        \"document\" =\u003e array:4 [▶]\n        //        \"highlights\" =\u003e array:1 [▶]\n        //        \"seq_id\" =\u003e 6\n        //    ]\n        // ]\n    }\n```\n\n### Querying Typesense\n\nThe class `TypesenseQuery()` class takes 2 arguments :\n\n* The search terme (`q`)\n* The fields to search on (`queryBy`)\n\nYou can create more complex queries using all the possible Typsense [search arguments](https://typesense.org/docs/0.21.0/api/documents.html#arguments)\n\n```php\n\u003c?php\n\nuse ACSEO\\TypesenseBundle\\Finder\\TypesenseQuery;\n\n$simpleQuery = new TypesenseQuery('search term', 'collection field to search in');\n\n$complexQuery = new TypesenseQuery('search term', 'collection field to search in')\n                      -\u003efilterBy('theme: [adventure, thriller]')\n                      -\u003eaddParameter('key', 'value')\n                      -\u003esortBy('year:desc');\n```\n\n### Create specific finder for a collection\n\nYou can easily create specific finders for each collection that you declare.\n\n```yaml\n# config/packages/acseo_typesense.yml\nacseo_typesense:\n    # ...\n    # Collection settings\n    collections:\n        books:                                       # Typesense collection name\n            # ...                                    # Colleciton fields definition\n            # ...\n            finders:                                 # Declare your specific finder\n                books_autocomplete:                  # Finder name\n                    finder_parameters:               # Parameters used by the finder\n                        query_by: title              #\n                        limit: 10                    # You can add as key / valuesspecifications\n                        prefix: true                 # based on Typesense Request \n                        num_typos: 1                 #\n                        drop_tokens_threshold: 1     #\n```\n\nThis configuration will create a service named `@typesense.finder.books.books_autocomplete`.  \nYou can inject the specific finder in your Controller or into other services\n\n```yaml\n# config/services.yaml\nservices:\n    App\\Controller\\BookController:\n        arguments:\n            $autocompleteBookFinder: '@typesense.finder.books.books_autocomplete'\n```\n\nand then use it like this :\n\n```php\n\u003c?php\n// src/Controller/BookController.php\n\nclass BookController extends AbstractController\n{\n    private $autocompleteBookFinder;\n\n    public function __construct($autocompleteBookFinder)\n    {\n        $this-\u003eautocompleteBookFinder = $autocompleteBookFinder;\n    }\n\n    public function autocomplete($term = '')\n    {\n        $results = $this-\u003eautocompleteBookFinder-\u003esearch($term)-\u003egetResults();\n        // or if you want raw results\n        $rawResults = $this-\u003eautocompleteBookFinder-\u003esearch($term)-\u003egetRawResults();\n    }\n```\n\n### Use different kind of services\n\nThis bundles creates different services that you can use in your Controllers or anywhere you want.\n\n* `typesense.client` : the basic client inherited from the official `typesense-php` package \n* `typesense.collection_client` : this service allows you to do basic actions on collections, and allows to perform `search` and `multisearch` action.\n* `typesense.finder.*` : this generated service allows you to perform `query` or `rawQuery` on a specific collection. Example of a generated service : `typesense.finder.candidates`\n* `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`\n\nNote : there a other services. You can use the `debug:container` command in order to see all of them.\n\n### Doctrine Listeners\n\nDoctrine listeners will update Typesense with Entity data during the following events :\n\n* postPersist\n* postUpdate\n* preDelete\n\n### Perform multisearch\n\nYou can create [multisearch](https://typesense.org/docs/0.21.0/api/documents.html#federated-multi-search) requests and get results using the `collectionClient` service.\n\n```php\n// Peform multisearch\n\n$searchRequests = [\n    (new TypesenseQuery('Jules'))-\u003eaddParameter('collection', 'author'),\n    (new TypesenseQuery('Paris'))-\u003eaddParameter('collection', 'library')  \n];\n\n$commonParams = new TypesenseQuery()-\u003eaddParameter('query_by', 'name');\n\n$response = $this-\u003ecollectionClient-\u003emultisearch($searchRequests, $commonParams);\n```\n\n## Cookbook \n----------------\n\n* [Use Typesense to make an autocomplete field](doc/cookbook/autocomplete.md)\n\n\n## Testing the Bundle\n\ntests are written in the `tests` directory.\n\n*  **Unit** tests doesn't require a running Typesense server\n*  **Functional** tests require a running Typesense server\n\nYou can launch the tests with the following commands : \n\n```bash\n# Unit test\n$ php ./vendor/bin/phpunit tests/Unit\n\n# Functional test\n# First, start a Typesense server with Docker\n$ composer run-script typesenseServer\n$ php ./vendor/bin/phpunit tests/Functional\n```\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facseo%2Ftypesensebundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Facseo%2Ftypesensebundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facseo%2Ftypesensebundle/lists"}