# Elasticsearch & OpenSearch Support ## Overview [Elasticsearch](https://www.elastic.co/elasticsearch/) and [OpenSearch](https://opensearch.org/) are distributed RESTful search and analytics engines capable of solving a growing number of use cases: application search, security analytics, metrics, logging, etc. OpenSearch is an open-source fork of Elasticsearch. API Platform comes natively with **reading** support for both Elasticsearch and OpenSearch. It uses internally the official PHP clients: [Elasticsearch-PHP](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html) or [OpenSearch-PHP](https://opensearch.org/docs/latest/clients/php/). API Platform supports Elasticsearch >= 7.11.0 < 8.0, Elasticsearch >= 8.4 < 9.0, and OpenSearch >= 2.x. Support for Elasticsearch 8 was introduced in API Platform 3.2, and OpenSearch support was introduced in API Platform 4.3. ## Enabling Reading Support To enable the reading support, require the appropriate PHP client using Composer. For Elasticsearch 8: ```console composer require elasticsearch/elasticsearch:^8.4 ``` For Elasticsearch 7: ```console composer require elasticsearch/elasticsearch:^7.11 ``` For OpenSearch: ```console composer require opensearch-project/opensearch-php:^2.5 ``` Then, enable it inside the API Platform configuration, using one of the configurations below: ### Enabling Reading Support using Symfony For Elasticsearch: ```yaml # api/config/packages/api_platform.yaml parameters: # ... env(ELASTICSEARCH_HOST): "http://localhost:9200" api_platform: # ... mapping: paths: ["%kernel.project_dir%/src/Model"] elasticsearch: hosts: ["%env(ELASTICSEARCH_HOST)%"] #... ``` For OpenSearch, set the `client` option to `opensearch`: ```yaml # api/config/packages/api_platform.yaml parameters: # ... env(OPENSEARCH_HOST): "http://localhost:9200" api_platform: # ... mapping: paths: ["%kernel.project_dir%/src/Model"] elasticsearch: client: opensearch hosts: ["%env(OPENSEARCH_HOST)%"] #... ``` #### SSL Configuration When connecting over HTTPS with self-signed certificates or custom Certificate Authorities, you can configure SSL verification. This works for both Elasticsearch and OpenSearch. **With a custom CA bundle:** ```yaml # config/packages/api_platform.yaml api_platform: elasticsearch: <<<<<<< HEAD hosts: ["%env(ELASTICSEARCH_HOST)%"] ssl_ca_bundle: "/path/to/ca-bundle.crt" ``` **Disable SSL verification (dev/test only):** ```yaml # config/packages/api_platform.yaml api_platform: elasticsearch: hosts: ["%env(ELASTICSEARCH_HOST)%"] ssl_verification: false # Never use in production ``` > [!NOTE] You cannot use both options together. ### Enabling Reading Support using Laravel For Elasticsearch: ```php [ 'paths' => [ base_path('app/Models'), ], ], 'elasticsearch' => [ 'hosts' => [ env('ELASTICSEARCH_HOST', 'http://localhost:9200'), ], ], ]; ``` For OpenSearch: ```php [ 'paths' => [ base_path('app/Models'), ], ], 'elasticsearch' => [ 'client' => 'opensearch', 'hosts' => [ env('OPENSEARCH_HOST', 'http://localhost:9200'), ], ], ]; ``` ## Creating Models API Platform follows the best practices of Elasticsearch: - a single index per resource should be used because Elasticsearch is going to [drop support for index types and will allow only a single type per index](https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html); - index name should be the short resource name in lower snake_case; - the default `_doc` type should be used; - all fields should be lower case and should use camelCase for combining words. This involves having mappings and models which absolutely match each other. Here is an example of mappings for 2 resources, `User` and `Tweet`, and their models: `PUT user` ```json { "mappings": { "_doc": { "properties": { "id": { "type": "keyword" }, "gender": { "type": "keyword" }, "age": { "type": "integer" }, "first_name": { "type": "text" }, "last_name": { "type": "text" }, "tweets": { "type": "nested", "properties": { "id": { "type": "keyword" }, "date": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "message": { "type": "text" } }, "dynamic": "strict" } }, "dynamic": "strict" } } } ``` `PUT tweet` ```json { "mappings": { "_doc": { "properties": { "id": { "type": "keyword" }, "author": { "properties": { "id": { "type": "keyword" }, "gender": { "type": "keyword" }, "age": { "type": "integer" }, "first_name": { "type": "text" }, "last_name": { "type": "text" } }, "dynamic": "strict" }, "date": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "message": { "type": "text" } }, "dynamic": "strict" } } } ``` ```php