You are here

public function SearchQuery::prepareAndNormalize in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/search/src/SearchQuery.php \Drupal\search\SearchQuery::prepareAndNormalize()

Prepares the query and calculates the normalization factor.

After the query is normalized the keywords are weighted to give the results a relevancy score. The query is ready for execution after this.

Error and warning conditions can apply. Call getStatus() after calling this method to retrieve them.

Return value

bool TRUE if at least one keyword matched the search index; FALSE if not.

2 calls to SearchQuery::prepareAndNormalize()
SearchQuery::countQuery in core/modules/search/src/SearchQuery.php
Builds the default count query for SearchQuery.
SearchQuery::preExecute in core/modules/search/src/SearchQuery.php
Generic preparation and validation for a SELECT query.

File

core/modules/search/src/SearchQuery.php, line 392

Class

SearchQuery
Search query extender and helper functions.

Namespace

Drupal\search

Code

public function prepareAndNormalize() {
  $this
    ->parseSearchExpression();
  $this->executedPrepare = TRUE;
  if (count($this->words) == 0) {

    // Although the query could proceed, there is no point in joining
    // with other tables and attempting to normalize if there are no
    // keywords present.
    $this->status |= SearchQuery::NO_POSITIVE_KEYWORDS;
    return FALSE;
  }

  // Build the basic search query: match the entered keywords.
  $or = $this->connection
    ->condition('OR');
  foreach ($this->words as $word) {
    $or
      ->condition('i.word', $word);
  }
  $this
    ->condition($or);

  // Add keyword normalization information to the query.
  $this
    ->join('search_total', 't', '[i].[word] = [t].[word]');
  $this
    ->condition('i.type', $this->type)
    ->groupBy('i.type')
    ->groupBy('i.sid');

  // If the query is simple, we should have calculated the number of
  // matching words we need to find, so impose that criterion. For non-
  // simple queries, this condition could lead to incorrectly deciding not
  // to continue with the full query.
  if ($this->simple) {
    $this
      ->having('COUNT(*) >= :matches', [
      ':matches' => $this->matches,
    ]);
  }

  // Clone the query object to calculate normalization.
  $normalize_query = clone $this->query;

  // For complex search queries, add the LIKE conditions; if the query is
  // simple, we do not need them for normalization.
  if (!$this->simple) {
    $normalize_query
      ->join('search_dataset', 'd', '[i].[sid] = [d].[sid] AND [i].[type] = [d].[type] AND [i].[langcode] = [d].[langcode]');
    if (count($this->conditions)) {
      $normalize_query
        ->condition($this->conditions);
    }
  }

  // Calculate normalization, which is the max of all the search scores for
  // positive keywords in the query. And note that the query could have other
  // fields added to it by the user of this extension.
  $normalize_query
    ->addExpression('SUM([i].[score] * [t].[count])', 'calculated_score');
  $result = $normalize_query
    ->range(0, 1)
    ->orderBy('calculated_score', 'DESC')
    ->execute()
    ->fetchObject();
  if (isset($result->calculated_score)) {
    $this->normalize = (double) $result->calculated_score;
  }
  if ($this->normalize) {
    return TRUE;
  }

  // If the normalization value was zero, that indicates there were no
  // matches to the supplied positive keywords.
  $this->status |= SearchQuery::NO_KEYWORD_MATCHES;
  return FALSE;
}