mirror of
https://github.com/Codappix/search_core.git
synced 2024-11-22 09:16:21 +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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trim($searchRequest->getSearchTerm()) === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$boostQueryParts = [];
|
$boostQueryParts = [];
|
||||||
|
|
||||||
foreach ($fields as $fieldName => $boostValue) {
|
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];
|
return [$config['field'] => $filter];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,20 +119,48 @@ E.g. you submit a filter in form of:
|
||||||
|
|
||||||
.. code-block:: html
|
.. code-block:: html
|
||||||
|
|
||||||
<f:form.textfield property="filter.distance.location.lat" value="51.168098" />
|
<f:comment>
|
||||||
<f:form.textfield property="filter.distance.location.lon" value="6.381384" />
|
Due to TYPO3 7.x fluid limitations, we build this input ourself.
|
||||||
<f:form.textfield property="filter.distance.distance" value="100km" />
|
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
|
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::
|
can add the following TypoScript, which will be added to the filter::
|
||||||
|
|
||||||
mapping {
|
mapping {
|
||||||
filter {
|
filter {
|
||||||
distance {
|
month {
|
||||||
field = geo_distance
|
type = range
|
||||||
|
field = released
|
||||||
|
raw {
|
||||||
|
format = yyyy-MM
|
||||||
|
}
|
||||||
|
|
||||||
fields {
|
fields {
|
||||||
distance = distance
|
gte = from
|
||||||
location = location
|
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
|
On the left hand side is the elasticsearch field name, on the right side the one submitted as a
|
||||||
filter.
|
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.
|
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:
|
||||||
|
|
||||||
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
|
* @test
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue