chameleon-system/elastic-integration-bundle
Integrates the elastic bundle into chameleon to allow searching/indexing items other than products
Requires
- php: ^7.4
- chameleon-system/elastic-bundle: ~7.1.0
- chameleon-system/chameleon-base: ~7.1.0
Suggests
- chameleon-system/item-list-bundle: To render elastic search results/filter
README
To create a new list using the ElasticBundle and the ItemListBundle, follow these instructions:
- Create your Index/Mapping for the chameleon elastic bundle (see readme in chameleon-system/elastic-bundle)
Example:
chameleon_system_elastic: indices: my_index_de: settings: common mappings: ["my_mapping"] language: 'de' my_index_en: settings: common mappings: ["my_mapping"] language: 'en' connection: - { host: "%env(string:ESONO_ELASTIC_HOST)%", port:%env(int:ESONO_ELASTIC_PORT)%} mappings: my_mapping: properties: name: type: text analyzer: "index_word_split" search_analyzer: "index_word_split" ... Create your indexer bei extending
\ChameleonSystem\ElasticBundle\Indexer\AbstractIndexer.Create a service definition for the indexer you just created, tagging it with
chameleon_system_elastic.indexer. The tag will need an alias, so you can call a specific indexer via the console. Example:<parameters> <parameter key="my_index_list" type="collection"> <parameter>my_index_de</parameter> <parameter>my_index_en</parameter> </parameter> </parameters> <service class="MyBundle\MyIndexer" id="my_bundle.my_indexer" parent="chameleon_system_elastic.indexer.abstract_indexer"> <!-- We use setter injection since the parent class already has a lot of parameters in its constructor. If the constructor of the parent ever changes, the setter injection will not be affected by that change. --> <call method="setIndexConfigurationNames"> <argument>%my_index_list%</argument> </call> <tag name="chameleon_system_elastic.indexer" alias="my_indexer"/> </service>This will create an indexer named
my_indexerwhich will fill the indexmy_index_deandmy_index_en.To periodically push changes via cms backend to elastic, add the relevant tables to the re-indexer:
chameleon_system_elastic_integration: reindex: # Controls which tables will generate reindex queue entries when being changed via backend. tablesToWatch: - my_table # In order to be able to process a reindex queue entry we need to know which indexers (it may be many) need to react to it. # So we need to map the tables to the aliases defined in the `chameleon_system_elastic.indexer` tag of these indexers. tablesToIndexerMapping: my_table: - my_indexerIf you need to add dynamic mappings to your document, you can do so by creating a MappingModifier (implement
\ChameleonSystem\Elastic\Interfaces\MappingModifierInterface) and tag withchameleon_system_elastic.mapping_modifier. Add the attributeindexto the tag, to select the indices the mapping should apply to. Example:<service class="MyBundle\MyMappingModifier" id="my_bundle.mapping_modifier"> <tag name="chameleon_system_elastic.mapping_modifier" index="my_index_*"/> </service>To Search/Filter, you should use the
chameleon-system/item-list-bundle. Implement a ListItemProvider (\ChameleonSystem\ItemList\Interfaces\ListItemProviderInterface) Since these providers tend to be very similar, you may consider basing them on\ChameleonSystem\ElasticIntegrationBundle\Bridge\Chameleon\ItemList\AbstractListItemProvider.Filtering and Sorting: The item list provider will need to interpret the filter and sort definitions you made for the
chameleon-system/item-list-bundle. This is done by defining a mapping between the filter definitions for your list and elastic search filter (implementing\ChameleonSystem\ElasticIntegration\Interfaces\FilterAggregationInterfaceor\ChameleonSystem\ElasticIntegration\Interfaces\FilterInterface) and a mapping between the sort definitions from your list and the elastic search sort options (implementing\ChameleonSystem\Elastic\Interfaces\SortInterface).
Example Mapping for Filter/Sorting using chameleon-system/item-list-bundle:
chameleon_system_item_list:
filter:
-
id: experience
title: my_theme_bndle.filter.experience_header
group: somegroup
view: /filter/experience.html.twig
-
id: currency
title: my_theme_bndle.filter.currency_header
group: somegroup
view: /filter/currency.html.twig
sort:
-
id: experience
title: "my_theme_bndle.sort.experience"
group: somegroup
chameleon_system_elastic_integration:
filterServiceMapping:
-
group: somegroup
id: experience
filterServiceId: my_bundle.filter.experience
-
group: somegroup
id: currency
filterServiceId: my_bundle.filter.currency
sortServiceMapping:
-
group: somegroup
id: experience
sortServiceId: my_bundle.sort.experience
Term Suggest API
If you want to provide term suggestions in a search field, as may make sense if you provide your users with the option to search in specific fields, then you can use the completion suggester api for this.
To use the API, you need to follow these steps:
Create a tree node to provide a URL for the API and assign it to the system page
\ChameleonSystem\ElasticIntegrationBundle\ChameleonSystemElasticIntegrationConstants::SYSTEM_PAGE_COMPLETION_SUGGESTERSet the proper mapping for the field (see https://www.elastic.co/guide/en/elasticsearch/reference/7.9/search-suggesters.html#completion-suggester):
"suggest": { "type": "completion" }Create a service for the class \ChameleonSystem\ElasticIntegration\CompletionSuggester\CompletionSuggester and configure it to do completion for your field.
<service class="ChameleonSystem\ElasticIntegration\CompletionSuggester\CompletionSuggester" id="app.completion_suggester.keywords" public="false"> <tag name="chameleon_system_elastic_integration.completion_suggester" field="keywords" /> <!-- note the "keywords" here. This will become part of the API URL --> <argument type="service" id="chameleon_system_elastic_integration.elastic_helper_collection"/> <argument type="service" id="chameleon_system_elastic.search_manager" /> <argument type="collection"><!-- list of indexes in which to search --> <argument>my_index</argument> </argument> <argument>keywords.suggest</argument><!-- the field configured for completion --> <argument type="collection"><!-- list of fields to return on completion. data is currently not used - but elastic wants this anyway. --> <argument>keywords</argument> </argument> <argument>10</argument><!-- number of suggestions to return --> </service>Suggestions should now be returned as a json array when you call the API
/path-to-system-page/keywords?string=foo