mirror of
https://github.com/Codappix/search_core.git
synced 2024-11-21 21:36:11 +01:00
FEATURE: Allow range queries for elasticsearch
Allow "raw" configuration and support "range" type. Also prevent adding boosts if no search term was submitted which can be boosted. Resolves: #119
This commit is contained in:
parent
74e5f6d432
commit
88f301f228
3 changed files with 107 additions and 8 deletions
|
@ -121,6 +121,10 @@ class QueryFactory
|
|||
return;
|
||||
}
|
||||
|
||||
if (trim($searchRequest->getSearchTerm()) === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$boostQueryParts = [];
|
||||
|
||||
foreach ($fields as $fieldName => $boostValue) {
|
||||
|
@ -238,6 +242,18 @@ class QueryFactory
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($config['raw'])) {
|
||||
$filter = array_merge($config['raw'], $filter);
|
||||
}
|
||||
|
||||
if ($config['type'] === 'range') {
|
||||
return [
|
||||
'range' => [
|
||||
$config['field'] => $filter,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return [$config['field'] => $filter];
|
||||
}
|
||||
|
||||
|
|
|
@ -119,20 +119,48 @@ E.g. you submit a filter in form of:
|
|||
|
||||
.. code-block:: html
|
||||
|
||||
<f:form.textfield property="filter.distance.location.lat" value="51.168098" />
|
||||
<f:form.textfield property="filter.distance.location.lon" value="6.381384" />
|
||||
<f:form.textfield property="filter.distance.distance" value="100km" />
|
||||
<f:comment>
|
||||
Due to TYPO3 7.x fluid limitations, we build this input ourself.
|
||||
No longer necessary in 8 and above
|
||||
</f:comment>
|
||||
<select name="tx_searchcore_search[searchRequest][filter][month][from]" class="_control" >
|
||||
<option value="">Month</option>
|
||||
<f:for each="{searchResult.facets.month.options}" as="month">
|
||||
<f:if condition="{month.count}">
|
||||
<option
|
||||
value="{month.displayName -> f:format.date(format: 'Y-m')}"
|
||||
{f:if(condition: '{searchRequest.filter.month.from} == {month.displayName -> f:format.date(format: \'Y-m\')}', then: 'selected="true"')}
|
||||
>{month.displayName -> f:format.date(format: '%B %Y')}</option>
|
||||
</f:if>
|
||||
</f:for>
|
||||
</select>
|
||||
<select name="tx_searchcore_search[searchRequest][filter][month][to]" class="_control" >
|
||||
<option value="">Month</option>
|
||||
<f:for each="{searchResult.facets.month.options}" as="month">
|
||||
<f:if condition="{month.count}">
|
||||
<option
|
||||
value="{month.displayName -> f:format.date(format: 'Y-m')}"
|
||||
{f:if(condition: '{searchRequest.filter.month.from} == {month.displayName -> f:format.date(format: \'Y-m\')}', then: 'selected="true"')}
|
||||
>{month.displayName -> f:format.date(format: '%B %Y')}</option>
|
||||
</f:if>
|
||||
</f:for>
|
||||
</select>
|
||||
|
||||
This will create a ``distance`` filter with subproperties. To make this filter actually work, you
|
||||
can add the following TypoScript, which will be added to the filter::
|
||||
|
||||
mapping {
|
||||
filter {
|
||||
distance {
|
||||
field = geo_distance
|
||||
month {
|
||||
type = range
|
||||
field = released
|
||||
raw {
|
||||
format = yyyy-MM
|
||||
}
|
||||
|
||||
fields {
|
||||
distance = distance
|
||||
location = location
|
||||
gte = from
|
||||
lte = to
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,9 +171,12 @@ in elasticsearch. In above example they do match, but you can also use different
|
|||
On the left hand side is the elasticsearch field name, on the right side the one submitted as a
|
||||
filter.
|
||||
|
||||
The ``field``, in above example ``geo_distance``, will be used as the elasticsearch field for
|
||||
The ``field``, in above example ``released``, will be used as the elasticsearch field for
|
||||
filtering. This way you can use arbitrary filter names and map them to existing elasticsearch fields.
|
||||
|
||||
Everything that is configured inside ``raw`` is passed, as is, to search service, e.g.
|
||||
elasticsearch.
|
||||
|
||||
.. _fields:
|
||||
|
||||
fields
|
||||
|
|
|
@ -86,6 +86,58 @@ class QueryFactoryTest extends AbstractUnitTestCase
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function rangeFilterIsAddedToQuery()
|
||||
{
|
||||
$this->configureConfigurationMockWithDefault();
|
||||
$this->configuration->expects($this->any())
|
||||
->method('getIfExists')
|
||||
->will($this->returnCallback(function ($configName) {
|
||||
if ($configName === 'searching.mapping.filter.month') {
|
||||
return [
|
||||
'type' => 'range',
|
||||
'field' => 'released',
|
||||
'raw' => [
|
||||
'format' => 'yyyy-MM',
|
||||
],
|
||||
'fields' => [
|
||||
'gte' => 'from',
|
||||
'lte' => 'to',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}));
|
||||
|
||||
$searchRequest = new SearchRequest('SearchWord');
|
||||
$searchRequest->setFilter([
|
||||
'month' => [
|
||||
'from' => '2016-03',
|
||||
'to' => '2017-11',
|
||||
],
|
||||
]);
|
||||
|
||||
$query = $this->subject->create($searchRequest);
|
||||
$this->assertSame(
|
||||
[
|
||||
[
|
||||
'range' => [
|
||||
'released' => [
|
||||
'format' => 'yyyy-MM',
|
||||
'gte' => '2016-03',
|
||||
'lte' => '2017-11',
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
$query->toArray()['query']['bool']['filter'],
|
||||
'Filter was not added to query.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue