Merge pull request #126 from Codappix/feature/119-allow-range-queries-for-elasticsearch

FEATURE: 119 allow range queries for elasticsearch
This commit is contained in:
Daniel Siepmann 2018-03-08 09:48:53 +01:00 committed by GitHub
commit 2a8f993721
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 107 additions and 8 deletions

View file

@ -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];
} }

View file

@ -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

View file

@ -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
*/ */