Example #1
0
 private function getQueryField(SearchQueryInterface $query)
 {
     $field = null;
     if ($query instanceof BooleanQueryInterface) {
         foreach ($query->getSubQueries() as $subQuery) {
             $subQueryField = $this->getQueryField($subQuery);
             if ($field && (!$subQueryField || $field !== $subQueryField)) {
                 return false;
             }
             if ($subQueryField) {
                 $field = $subQueryField;
             }
         }
     } elseif ($query instanceof FieldQueryInterface) {
         $field = $query->getField();
     }
     return $field;
 }
Example #2
0
 /**
  * @param SearchQueryInterface $query
  * @return array
  */
 protected function mapQuery(SearchQueryInterface $query)
 {
     $queryArr = [];
     if ($query instanceof Boolean) {
         $signs = $query->getSigns();
         $boolean = [];
         foreach ($query->getSubQueries() as $key => $subQuery) {
             $sign = isset($signs[$key]) ? $signs[$key] : null;
             switch ($sign) {
                 case true:
                     if ($subQueryArr = $this->mapQuery($subQuery)) {
                         if (!isset($boolean['must'])) {
                             $boolean['must'] = [];
                         }
                         $boolean['must'][] = $this->mapQuery($subQuery);
                     }
                     break;
                 case false:
                     if ($subQueryArr = $this->mapQuery($subQuery)) {
                         if (!isset($booleanr['must_not'])) {
                             $boolean['must_not'] = [];
                         }
                         $boolean['must_not'][] = $this->mapQuery($subQuery);
                     }
                     break;
                 case null:
                     if ($subQueryArr = $this->mapQuery($subQuery)) {
                         if (!isset($boolean['should'])) {
                             $boolean['should'] = [];
                         }
                         $boolean['should'][] = $this->mapQuery($subQuery);
                     }
                     break;
             }
         }
         if ($boolean) {
             $queryArr['bool'] = $boolean;
         }
     } elseif ($query instanceof Term) {
         $queryArr['term'] = [$query->getField() => $query->getTerm()];
     } elseif ($query instanceof Range) {
         $range = [];
         if (($from = $query->getLowerBound()) !== null) {
             $range[$query->isIncludeLowerBound() ? 'gte' : 'gt'] = $from;
         }
         if (($to = $query->getUpperBound()) !== null) {
             $range[$query->isIncludeUpperBound() ? 'lte' : 'lt'] = $to;
         }
         $queryArr['range'] = [$query->getField() => $range];
     }
     return $queryArr;
 }
Example #3
0
 /**
  * Returns condition by search query.
  *
  * @param SearchQueryInterface $query
  * @return array
  */
 protected function getCondition(SearchQueryInterface $query)
 {
     $condition = [];
     /** @var ActiveRecord $modelClass */
     $modelClass = $this->modelClass;
     $table = $modelClass::tableName();
     if ($query instanceof Boolean) {
         $operator = reset($query->getSigns()) === null ? 'or' : 'and';
         $condition = [$operator];
         foreach ($query->getSubQueries() as $subQuery) {
             $condition[] = $this->getCondition($subQuery);
         }
     } elseif ($query instanceof Term) {
         $field = $table . '.' . $query->getField();
         $childName = '';
         if (($pos = strrpos($query->getField(), '.')) !== false) {
             $childName = substr($query->getField(), $pos + 1);
             $name = substr($query->getField(), 0, $pos);
         } else {
             $name = $query->getField();
         }
         $attribute = $this->getSearchableAttribute($name);
         if ($attribute->value and $attribute->value instanceof \Closure) {
             $attributeValue = call_user_func_array($attribute->value, [new $this->modelClass()]);
             if ($attributeValue instanceof ActiveQuery) {
                 $modelClass = $attributeValue->modelClass;
                 $relationTable = $modelClass::tableName();
                 if (!isset($this->_joined[$attribute->name])) {
                     $this->joinWith($attribute->name, false);
                     $this->_joined[$attribute->name] = true;
                 }
                 $field = $relationTable . '.' . ($childName ?: $name);
             }
         }
         $value = $query->getTerm();
         $condition = is_array($value) ? ['in', $field, $value] : [$field => $value];
     } elseif ($query instanceof Range) {
         if (($from = $query->getLowerBound()) !== null) {
             $condition[] = [$query->isIncludeLowerBound() ? '>=' : '>', $table . '.' . $query->getField(), $from];
         }
         if (($to = $query->getUpperBound()) !== null) {
             $condition[] = [$query->isIncludeLowerBound() ? '<=' : '<', $table . '.' . $query->getField(), $to];
         }
         if ($condition) {
             $condition = count($condition) == 1 ? $condition[0] : array_merge(['and'], $condition);
         }
     }
     return $condition;
 }
Example #4
0
 /**
  * @inheritdoc
  */
 public function equals(SearchQueryInterface $query)
 {
     $sameField = $query instanceof Range && $this->getField() === $query->getField();
     return $sameField && ($this->getLowerBound() === $query->getLowerBound() && $this->getUpperBound() === $query->getUpperBound() && $this->isIncludeLowerBound() === $query->isIncludeLowerBound() && $this->isIncludeUpperBound() === $query->isIncludeUpperBound()) ? 1 : ($sameField ? 0 : -1);
 }
Example #5
0
 /**
  * @param SearchQueryInterface $query
  * @param bool $asFilter
  * @return array
  */
 protected function mapQuery(SearchQueryInterface $query, $asFilter = false)
 {
     $queryArr = [];
     if ($query instanceof Boolean) {
         $signs = $query->getSigns();
         $boolean = [];
         foreach ($query->getSubQueries() as $key => $subQuery) {
             $sign = isset($signs[$key]) ? $signs[$key] : null;
             if ($sign === true) {
                 if ($subQueryArr = $this->mapQuery($subQuery, $asFilter)) {
                     if (!isset($boolean['must'])) {
                         $boolean['must'] = [];
                     }
                     $boolean['must'][] = $this->mapQuery($subQuery, $asFilter);
                 }
             } elseif ($sign === false) {
                 if ($subQueryArr = $this->mapQuery($subQuery, $asFilter)) {
                     if (!isset($booleanr['must_not'])) {
                         $boolean['must_not'] = [];
                     }
                     $boolean['must_not'][] = $this->mapQuery($subQuery, $asFilter);
                 }
             } elseif ($sign === null) {
                 if ($subQueryArr = $this->mapQuery($subQuery, $asFilter)) {
                     if (!isset($boolean['should'])) {
                         $boolean['should'] = [];
                     }
                     $boolean['should'][] = $this->mapQuery($subQuery, $asFilter);
                 }
             }
         }
         if ($boolean) {
             $queryArr['bool'] = $boolean;
         }
     } elseif ($query instanceof Term) {
         $queryArr['term'] = [$query->getField() => $query->getTerm()];
     } elseif ($query instanceof Range) {
         $range = [];
         if (($from = $query->getLowerBound()) !== null) {
             $range[$query->isIncludeLowerBound() ? 'gte' : 'gt'] = $from;
         }
         if (($to = $query->getUpperBound()) !== null) {
             $range[$query->isIncludeUpperBound() ? 'lte' : 'lt'] = $to;
         }
         $queryArr['range'] = [$query->getField() => $range];
     } elseif ($query instanceof Match) {
         $matchQuery = [$query->getField() => $query->getTerm()->getTerm()];
         if ($asFilter) {
             $queryArr['query']['match'] = $matchQuery;
         } else {
             $queryArr['match'] = $matchQuery;
         }
     } elseif ($query instanceof MultiMatch) {
         $multiMatchQuery = ['query' => $query->getTerm()->getTerm(), 'type' => 'most_fields', 'fields' => array_values($query->getFields()), 'minimum_should_match' => '75%'];
         if ($asFilter) {
             $queryArr['query']['multi_match'] = $multiMatchQuery;
         } else {
             $queryArr['multi_match'] = $multiMatchQuery;
         }
     }
     return $queryArr;
 }
Example #6
0
 /**
  * Applies full text search settings to query.
  *
  * @param SearchQueryInterface $searchQuery
  * @param AttributeDescriptor[] $fullTextSearchAttributes
  * @param string $fullTextSearchParam
  * @return SearchQueryInterface
  */
 public function applyFullTextSearchSettings(SearchQueryInterface $searchQuery, $fullTextSearchAttributes, $fullTextSearchParam = 'text')
 {
     if ($fullTextSearchAttributes) {
         if ($searchQuery instanceof BooleanQueryInterface) {
             $subQueries = $searchQuery->getSubQueries();
             $signs = $searchQuery->getSigns();
             foreach ($subQueries as $key => $subQuery) {
                 $subQueries[$key] = $this->applyFullTextSearchSettings($subQuery, $fullTextSearchAttributes, $fullTextSearchParam);
             }
             $searchQuery->setSubQueries($subQueries, $signs);
         } elseif ($searchQuery instanceof Term) {
             $field = $searchQuery->getField();
             if ($field == $fullTextSearchParam) {
                 $fields = array_map(function (AttributeDescriptor $attribute) {
                     return $attribute->name;
                 }, $fullTextSearchAttributes);
                 $searchQuery = new MultiMatch($fields, $searchQuery);
             } elseif (array_filter($fullTextSearchAttributes, function (AttributeDescriptor $attribute) use($field) {
                 return $attribute->name == $field;
             })) {
                 $searchQuery = new Match($searchQuery->getField(), $searchQuery);
             }
         }
     }
     return $searchQuery;
 }
 protected static function removeQueryByFieldName(SearchQueryInterface $fromQuery, $field, $sign = true)
 {
     if ($fromQuery instanceof BooleanQueryInterface) {
         $subQueries = $fromQuery->getSubQueries();
         $signs = $fromQuery->getSigns();
         $removed = false;
         foreach ($subQueries as $key => $subQuery) {
             if ($subQuery instanceof FieldQueryInterface) {
                 if ($signs[$key] === $sign && $subQuery->getField() === $field) {
                     unset($subQueries[$key], $signs[$key]);
                     $removed = true;
                 }
             }
         }
         if (!$removed) {
             foreach ($subQueries as $key => $subQuery) {
                 if ($subQuery instanceof BooleanQueryInterface) {
                     $subQueries[$key] = self::removeQueryByFieldName($subQuery, $field, $sign);
                 }
             }
         }
         $fromQuery->setSubQueries($subQueries, $signs);
     } elseif ($fromQuery instanceof FieldQueryInterface && $fromQuery->getField() === $field) {
         return new Boolean();
     }
     return $fromQuery;
 }