You are here

public function Database::search in Search API 8

Executes a search on this server.

Parameters

\Drupal\search_api\Query\QueryInterface $query: The query to execute.

Throws

\Drupal\search_api\SearchApiException Thrown if an error prevented the search from completing.

Overrides BackendSpecificInterface::search

File

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

Class

Database
Indexes and searches items using the database.

Namespace

Drupal\search_api_db\Plugin\search_api\backend

Code

public function search(QueryInterface $query) {
  $this->ignored = $this->warnings = [];
  $index = $query
    ->getIndex();
  $db_info = $this
    ->getIndexDbInfo($index);
  if (!isset($db_info['field_tables'])) {
    $index_id = $index
      ->id();
    throw new SearchApiException("No field settings saved for index with ID '{$index_id}'.");
  }
  $fields = $this
    ->getFieldInfo($index);
  $fields['search_api_id'] = [
    'column' => 'item_id',
  ];
  $db_query = $this
    ->createDbQuery($query, $fields);
  $results = $query
    ->getResults();
  try {
    $skip_count = $query
      ->getOption('skip result count');
    $count = NULL;
    if (!$skip_count) {
      $count_query = $db_query
        ->countQuery();
      $count = $count_query
        ->execute()
        ->fetchField();
      $results
        ->setResultCount($count);
    }

    // With a "min_count" of 0, some facets can even be available if there are
    // no results.
    if ($query
      ->getOption('search_api_facets')) {
      $facets = $this
        ->getFacets($query, clone $db_query, $count);
      $results
        ->setExtraData('search_api_facets', $facets);
    }

    // Everything else can be skipped if the count is 0.
    if ($skip_count || $count) {
      $query_options = $query
        ->getOptions();
      if (isset($query_options['offset']) || isset($query_options['limit'])) {
        $offset = $query_options['offset'] ?? 0;
        $limit = $query_options['limit'] ?? 1000000;
        $db_query
          ->range($offset, $limit);
      }
      $this
        ->setQuerySort($query, $db_query, $fields);
      $result = $db_query
        ->execute();
      foreach ($result as $row) {
        $item = $this
          ->getFieldsHelper()
          ->createItem($index, $row->item_id);
        $item
          ->setScore($row->score / self::SCORE_MULTIPLIER);
        $results
          ->addResultItem($item);
      }
      if ($skip_count && !empty($item)) {
        $results
          ->setResultCount(1);
      }
    }
  } catch (DatabaseException $e) {
    if ($query instanceof RefinableCacheableDependencyInterface) {
      $query
        ->mergeCacheMaxAge(0);
    }
    throw new SearchApiException('A database exception occurred while searching.', $e
      ->getCode(), $e);
  } catch (\PDOException $e) {
    if ($query instanceof RefinableCacheableDependencyInterface) {
      $query
        ->mergeCacheMaxAge(0);
    }
    throw new SearchApiException('A database exception occurred while searching.', $e
      ->getCode(), $e);
  }

  // Add additional warnings and ignored keys.
  $metadata = [
    'warnings' => 'addWarning',
    'ignored' => 'addIgnoredSearchKey',
  ];
  foreach ($metadata as $property => $method) {
    foreach (array_keys($this->{$property}) as $value) {
      $results
        ->{$method}($value);
    }
  }
}