Open Search
Configuration
# packages/headless.yaml
opendxp_headless:
opensearch:
hosts: # your index hosts
credentials: # your index credentials
API Search types
It is possible, to preconfigure specific search types:
# packages/headless.yaml
opendxp_headless:
# enable, if you want to have search types
api_search_types:
my_search_type: {}
my_extended_search_type:
additional_filter:
- special_filter # (additional filters, see Api Filter)
action_response:
response_class: 'App\Domain\Search\ResponseEntity\MyExtendedSearchResponse'
this will create the endpoints search/my-search-type and search/my-extended-search-type.
Search PHP API
This bundle provides a service to query an opensearch index.
Use the service HeadlessBundle\OpenSearch\Service\OpenSearchService to perform a search:
use OpenDxp\Bundle\HeadlessBundle\OpenSearch\Dto\OpenSearchDemand;
use OpenDxp\Bundle\HeadlessBundle\OpenSearch\Service\OpenSearchService;
class MySearchService {
public function __construct(protected OpenSearchService $openSearchService)
{}
public function mySearch()
{
$searchDemand = new OpenSearchDemand();
$searchDemand->setLocale('en');
$searchDemand->setOffset(0);
$searchDemand->setLimit(200);
$searchDemand->setOrder('id');
$searchDemand->setOrderDirection('desc');
$searchDemand->addConstraints([
'first_constraint': 'abc',
'second_constraint': 124
]);
// use a 'search type' of your choice
$result = $this->openSearchService->search('my_search_type', $searchDemand);
// do something with the result
$result->getHits();
$result->getTotalCount();
$result->getAggregations();
}
}
In order to modify the search, listen to the events provided:
class MySearchEventListener implements EventSubscriberInterface {
public function getSubscribedEvents(): array
{
return [
OpenSearchEvents::POST_BUILD_SORTS => ['onPostBuildSorts'],
OpenSearchEvents::POST_BUILD_QUERY => ['onPostBuildQuery', 10], // lower priority
OpenSearchEvents::POST_BUILD_POST_FILTER => ['onPostBuildPostFilter'],
OpenSearchEvents::POST_BUILD_AGGREGATIONS => ['onPostBuildAggregations']
OpenSearchEvents::PRE_SEARCH => ['onPreSearch']
];
}
public function onPreSearch(PreSearchEvent $event): void
{
// check for correct search type
if ($event->getSearchType() !== 'my_search_type') {
return;
}
// last change to modify the search demand, before the search will be performed
// example: change the index which will be queried
$searchDemand = $event->getSearchDemand();
$searchDemand->setIndex('my_other_index');
}
public function onPostBuildSorts(PostBuildSortsEvent $event): void
{
// check for correct search type
if ($event->getSearchType() !== 'my_search_type') {
return;
}
$sorts = $event->getSorts();
// modify existing sorts, or override with your own
$event->setSorts([new FieldSort('my_field', FieldSort::DESC)]);
}
public function onPostBuildQuery(PostBuildQueryEvent $event): void
{
// check for correct search type
if ($event->getSearchType() !== 'my_search_type') {
return;
}
$query = $event->getQuery();
$searchDemand = $event->getSearchDemand();
if (
$searchDemand->hasConstraint('first_constraint') &&
$searchDemand->getConstraint('first_constraint') == 'abc'
) {
// modify query based on your constraints
$query->add(new TermQuery('my_field', 'my_value'));
}
}
//...
}
Dynamic Search
This bundle works perfectly in conjunction with dynamic search bundle (open-dxp/dynamic-search-bundle) and the open search index provider bundle(open-dxp/dynamic-search-index-provider-opensearch-bundle).
Index mapping definition
To build document definitions for OpenDXP elements, extend from OpenDxp\Bundle\HeadlessBundle\DynamicSearch\Definition\Document\AbstractElementDefinition
Field Transformer
Generating element urls from cli is hard.
Use the provided OpenDxp\Bundle\HeadlessBundle\ThirdParty\DynamicSearch\Transformer\Field\ElementPathExtractor to generate your element urls while indexing.
Example:
$definition
->addSimpleDocumentFieldDefinition([
'name' => 'frontend_path',
'index_transformer' => [
'type' => 'explicit',
'configuration' => [
'type' => 'text',
'index' => false
]
],
'data_transformer' => [
'type' => ElementPathExtractor::class,
'configuration' => [
'arguments' => [
'locale' => $normalizerOptions['locale'] ?? null,
'site' => $this->getSite()
]
]
]
]);