-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
class FilterToElasticSearchQuery
{
const MUST_NOT = 'must_not';
const MUST = 'must';
const SHOULD = 'should';
/**
* @param FilterInterface $filter
* @param array $mapping
* @return array
*/
public static function filter(FilterInterface $filter, array $mapping): array
{
$conditions = [];
foreach ($filter->filters() as $condition => $filters) {
$filters = self::removeEmptyFilters($filters);
if (count($filters) > 0) {
self::processConditions($mapping, $conditions, $condition, $filters);
}
}
return $conditions;
}
/**
* @param array $filters
*
* @return array
*/
private static function removeEmptyFilters(array $filters)
{
$filters = array_filter(
$filters,
function ($v) {
return count($v) > 0;
}
);
return $filters;
}
/**
* @param array $mapping
* @param array $conditions
* @param $condition
* @param array $filters
*/
private static function processConditions(
array &$mapping,
array &$conditions,
$condition,
array &$filters
) {
switch ($condition) {
case self::MUST:
self::apply($mapping, $conditions, $filters, 'must');
break;
case self::MUST_NOT:
self::apply($mapping, $conditions, $filters, 'must_not');
break;
case self::SHOULD:
self::apply($mapping, $conditions, $filters, 'should');
break;
}
}
/**
* @param array $mapping
* @param array $conditions
* @param array $filters
* @param $operator
*/
protected static function apply(
array &$mapping,
array &$conditions,
array $filters,
$operator
) {
foreach ($filters as $filterName => $valuePair) {
foreach ($valuePair as $key => $value) {
if (false === array_key_exists($key, $mapping)) {
break;
}
$key = self::fetchColumnName($mapping, $key);
if (is_array($value) && count($value) > 0) {
$value = array_values($value);
if (count($value[0]) > 1) {
switch ($filterName) {
case BaseFilter::RANGES:
self::rangeQuery($conditions, $operator, $key, $value);
break;
case BaseFilter::NOT_RANGES:
$operator = self::getOppositeOperator($operator);
self::rangeQuery($conditions, $operator, $key, $value);
break;
}
} else {
switch ($filterName) {
case BaseFilter::GROUP:
$operatorIn = 'should';
if (self::MUST_NOT === $operator) {
$operatorIn = 'should_not';
}
self::inGroupQuery($conditions, $operatorIn, $key, $value);
break;
case BaseFilter::NOT_GROUP:
$operatorIn = 'should_not';
if (self::MUST_NOT === self::getOppositeOperator($operator)) {
$operatorIn = 'should';
}
self::inGroupQuery($conditions, $operatorIn, $key, $value);
break;
}
}
}
$value = (array)$value;
$value = array_shift($value);
switch ($filterName) {
case BaseFilter::GREATER_THAN_OR_EQUAL:
self::query($conditions, $operator, $key, 'gte', $value);
break;
case BaseFilter::GREATER_THAN:
self::query($conditions, $operator, $key, 'gt', $value);
break;
case BaseFilter::LESS_THAN_OR_EQUAL:
self::query($conditions, $operator, $key, 'lte', $value);
break;
case BaseFilter::LESS_THAN:
self::query($conditions, $operator, $key, 'lt', $value);
break;
case BaseFilter::CONTAINS:
self::query($conditions, $operator, $key, 'match', '*' . $value . '*');
break;
case BaseFilter::NOT_CONTAINS:
$operator = self::getOppositeOperator($operator);
self::query($conditions, $operator, $key, 'match', '*' . $value . '*');
break;
case BaseFilter::EQUALS:
self::query($conditions, $operator, $key, 'match', $value);
break;
case BaseFilter::NOT_EQUAL:
$operator = self::getOppositeOperator($operator);
self::query($conditions, $operator, $key, 'match', $value);
break;
case BaseFilter::EMPTY_FILTER:
self::query($conditions, $operator, $key, 'match', null);
break;
case BaseFilter::NOT_EMPTY:
$operator = self::getOppositeOperator($operator);
self::query($conditions, $operator, $key, 'match', null);
break;
case BaseFilter::ENDS_WITH:
$newValue = '*' . $value;
self::query($conditions, $operator, $key, 'match', $newValue);
break;
case BaseFilter::NOT_ENDS:
$operator = self::getOppositeOperator($operator);
self::query($conditions, $operator, $key, 'match', '*' . $value);
break;
case BaseFilter::STARTS_WITH:
self::query($conditions, $operator, $key, 'match', '*' . $value);
break;
case BaseFilter::NOT_STARTS:
$operator = self::getOppositeOperator($operator);
self::query($conditions, $operator, $key, 'match', $value . '*');
break;
}
}
}
}
/**
* @param $columns
* @param $propertyName
*
* @return int
*/
protected static function fetchColumnName(array &$columns, $propertyName)
{
if (empty($columns[$propertyName])) {
throw new \RuntimeException(sprintf('Property %s has no associated column.', $propertyName));
}
return $columns[$propertyName];
}
/**
* @param array $conditions
* @param $operator
* @param $key
* @param $value
*/
protected static function rangeQuery(array &$conditions, $operator, $key, $value)
{
$rangeCondition = ['gte' => $value[0][0], 'lte' => $value[0][1]];
if (self::MUST_NOT === $operator) {
$rangeCondition = ['lt' => $value[0][0], 'gt' => $value[0][1]];
}
$conditions['query']['bool']['filter'][] = ['range' => [$key => $rangeCondition]];
$conditions['query']['bool']['filter'] = array_values($conditions['query']['bool']['filter']);
}
/**
* @param $operator
* @return string
*/
protected static function getOppositeOperator($operator): string
{
if ($operator === self::MUST) {
$operator = self::MUST_NOT;
}
if ($operator === self::MUST_NOT) {
$operator = self::MUST;
return $operator;
}
return $operator;
}
/**
* @param array $conditions
* @param $operator
* @param $key
* @param $value
*/
protected static function inGroupQuery(array &$conditions, $operator, $key, $value)
{
$query = [
['bool' => [$operator => ['exists' => ['field' => $key]]]]
];
foreach ($value as $v) {
$query[] = ['match' => [$key => $v]];
}
$conditions['query']['bool']['filter']['bool'][$operator][] = $query;
}
/**
* @param array $conditions
* @param $operator
* @param $key
* @param $op
* @param $value
*/
protected static function query(array &$conditions, $operator, $key, $op, $value)
{
$conditions['query']['bool'][$operator][] = [$op => [$key => $value]];
}
}Metadata
Metadata
Assignees
Labels
No labels