You are here

protected function Database::createDbQuery in Search API 8

Creates a database query for a search.

Used as a helper method in search() and getAutocompleteSuggestions().

Parameters

\Drupal\search_api\Query\QueryInterface $query: The search query for which to create the database query.

array $fields: The internal field information to use.

Return value

\Drupal\Core\Database\Query\SelectInterface A database query object which will return the appropriate results (except for the range and sorting) for the given search query.

Throws

\Drupal\search_api\SearchApiException Thrown if some illegal query setting (unknown field, etc.) was encountered.

3 calls to Database::createDbQuery()
Database::getAutocompleteSuggestions in modules/search_api_db/src/Plugin/search_api/backend/Database.php
Retrieves autocompletion suggestions for some user input.
Database::getFacets in modules/search_api_db/src/Plugin/search_api/backend/Database.php
Computes facets for a search query.
Database::search in modules/search_api_db/src/Plugin/search_api/backend/Database.php
Executes a search on this server.

File

modules/search_api_db/src/Plugin/search_api/backend/Database.php, line 1727

Class

Database
Indexes and searches items using the database.

Namespace

Drupal\search_api_db\Plugin\search_api\backend

Code

protected function createDbQuery(QueryInterface $query, array $fields) {
  $keys =& $query
    ->getKeys();
  $keys_set = (bool) $keys;
  $tokenizer_active = $query
    ->getIndex()
    ->isValidProcessor('tokenizer');
  $keys = $this
    ->prepareKeys($keys, $tokenizer_active);

  // Only filter by fulltext keys if there are any real keys present.
  if ($keys && (!is_array($keys) || count($keys) > 2 || !isset($keys['#negation']) && count($keys) > 1)) {

    // Special case: if the outermost $keys array has "#negation" set, we
    // can't handle it like other negated subkeys. To avoid additional
    // complexity later, we just wrap $keys so it becomes a subkey.
    if (!empty($keys['#negation'])) {
      $keys = [
        '#conjunction' => 'AND',
        $keys,
      ];
    }
    $fulltext_fields = $this
      ->getQueryFulltextFields($query);
    if (!$fulltext_fields) {
      throw new SearchApiException('Search keys are given but no fulltext fields are defined.');
    }
    $fulltext_field_information = [];
    foreach ($fulltext_fields as $name) {
      if (!isset($fields[$name])) {
        throw new SearchApiException("Unknown field '{$name}' specified as search target.");
      }
      if (!$this
        ->getDataTypeHelper()
        ->isTextType($fields[$name]['type'])) {
        $types = $this
          ->getDataTypePluginManager()
          ->getInstances();
        $type = $types[$fields[$name]['type']]
          ->label();
        throw new SearchApiException("Cannot perform fulltext search on field '{$name}' of type '{$type}'.");
      }
      $fulltext_field_information[$name] = $fields[$name];
    }
    $db_query = $this
      ->createKeysQuery($keys, $fulltext_field_information, $fields, $query
      ->getIndex());
  }
  elseif ($keys_set) {
    $msg = $this
      ->t('No valid search keys were present in the query.');
    $this->warnings[(string) $msg] = 1;
  }
  if (!isset($db_query)) {
    $db_info = $this
      ->getIndexDbInfo($query
      ->getIndex());
    $db_query = $this->database
      ->select($db_info['index_table'], 't');
    $db_query
      ->addField('t', 'item_id', 'item_id');
    $db_query
      ->addExpression(':score', 'score', [
      ':score' => self::SCORE_MULTIPLIER,
    ]);
    $db_query
      ->distinct();
  }
  $condition_group = $query
    ->getConditionGroup();
  $this
    ->addLanguageConditions($condition_group, $query);
  if ($condition_group
    ->getConditions()) {
    $condition = $this
      ->createDbCondition($condition_group, $fields, $db_query, $query
      ->getIndex());
    if ($condition) {
      $db_query
        ->condition($condition);
    }
  }
  $db_query
    ->addTag('search_api_db_search');
  $db_query
    ->addMetaData('search_api_query', $query);
  $db_query
    ->addMetaData('search_api_db_fields', $fields);

  // Allow subclasses and other modules to alter the query (before a count
  // query is constructed from it).
  $event_base_name = SearchApiDbEvents::QUERY_PRE_EXECUTE;
  $event = new QueryPreExecuteEvent($db_query, $query);
  $this
    ->getEventDispatcher()
    ->dispatch($event_base_name, $event);
  $db_query = $event
    ->getDbQuery();
  $description = 'This hook is deprecated in search_api:8.x-1.16 and is removed from search_api:2.0.0. Please use the "search_api_db.query_pre_execute" event instead. See https://www.drupal.org/node/3103591';
  $this
    ->getModuleHandler()
    ->alterDeprecated($description, 'search_api_db_query', $db_query, $query);
  $this
    ->preQuery($db_query, $query);
  return $db_query;
}