diff -u b/core/modules/search/lib/Drupal/search/SearchQuery.php b/core/modules/search/lib/Drupal/search/SearchQuery.php --- b/core/modules/search/lib/Drupal/search/SearchQuery.php +++ b/core/modules/search/lib/Drupal/search/SearchQuery.php @@ -15,20 +15,10 @@ /** * Performs a query on the full-text search index for a word or words. * - * This function is normally only called by each plugin that supports the - * indexed search. + * This query is used by search plugins that use the search index (not all + * search plugins do, as some use a different searching mechanism). * - * Results are retrieved in two logical passes. However, the two passes are - * joined together into a single query, and in the case of most simple queries - * the second pass is not even used. - * - * The first pass selects a set of all possible matches, which has the benefit - * of also providing the exact result set for simple "AND" or "OR" searches. - * - * The second portion of the query further refines this set by verifying - * advanced text conditions (such as negative or phrase matches). - * - * The used query object has the tag 'search_$type' and can be further + * The query object is given the tag 'search_$type' and can be further * extended with hook_query_alter(). */ class SearchQuery extends SelectExtender { @@ -42,9 +32,8 @@ /** * The type of search (search type). * - * This maps to the value of the type column in search_index, and is equal - * to the machine-readable name of the entity type being indexed, or other - * identifier provided by a search plugin. + * This maps to the value of the type column in search_index, and is usually + * equal to the machine-readable name of the search plugin. * * @var string */ @@ -58,7 +47,7 @@ protected $keys = array('positive' => array(), 'negative' => array()); /** - * Indicates whether the first pass query requires complex conditions (LIKE). + * Indicates whether the query conditions are simple or complex (LIKE). * * @var bool */ @@ -67,8 +56,8 @@ /** * Conditions that are used for exact searches. * - * This is always used for the second pass query but not for the first pass, - * unless $this->simple is FALSE. + * This is always used for the second step in the query, but it is not part + * of the preparation step unless $this->simple is FALSE. * * @var DatabaseCondition */ @@ -93,16 +82,16 @@ /** * Multiplier for the normalized search score. * - * This value is calculated by the first pass query and multiplied with the - * actual score of a specific word to make sure that the resulting calculated - * score is between 0 and 1. + * This value is calculated by preparation step and multiplied by the actual + * score of a specific word to make sure that the resulting calculated score + * is between 0 and 1. * * @var float */ protected $normalize; /** - * Indicates whether the first pass query has been executed. + * Indicates whether the preparation step has been executed. * * @var bool */ @@ -134,8 +123,8 @@ /** * Whether or not search expressions were ignored. * - * The maximum number of AND/OR combinations exceeded can be configured to - * avoid Denial-of-Service attacks. Expressions beyond the limit are ignored. + * The maximum number of AND/OR combinations can be configured to avoid + * Denial-of-Service attacks. Expressions beyond the limit are ignored. * * @var bool */ @@ -162,7 +151,12 @@ /** * Parses the search query into SQL conditions. * - * We build two queries that match the dataset bodies. + * Sets up the following variables: + * - $this->keys + * - $this->words + * - $this->conditions + * - $this->simple + * - $this->matches */ protected function parseSearchExpression() { // Matchs words optionally prefixed by a dash. A word in this case is @@ -290,7 +284,11 @@ } /** - * Helper function for parseQuery(). + * Parses a word or phrase for parseQuery(). + * + * Splits a phrase into words. Adds its words to $this->words, if it is not + * already there. Returns a list containing the number of new words found, + * and the total number of words in the phrase. */ protected function parseWord($word) { $num_new_scores = 0; @@ -312,9 +310,9 @@ } /** - * Prepares and normalizes the query. + * Prepares the query and calculates the normalization factor. * - * After the query is normalised the keywords are weighted to give the results + * After the query is normalized the keywords are weighted to give the results * a relevancy score. The query is ready for execution after this. * * @return bool @@ -332,6 +330,7 @@ } $this->executedPrepare = TRUE; + // Build the basic search query. if (!empty($this->words)) { $or = db_or(); foreach ($this->words as $word) { @@ -339,7 +338,6 @@ } $this->condition($or); } - // Build query for keyword normalization. $this->join('search_total', 't', 'i.word = t.word'); $this ->condition('i.type', $this->type) @@ -347,18 +345,18 @@ ->groupBy('i.sid') ->having('COUNT(*) >= :matches', array(':matches' => $this->matches)); - // Clone the query object to do the firstPass query; - $first = clone $this->query; + // Clone the query object to calculate the normalization factor. + $normalize_query = clone $this->query; - // For complex search queries, add the LIKE conditions to the first pass query. + // For complex search queries, add the LIKE conditions. if (!$this->simple) { - $first->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type'); - $first->condition($this->conditions); + $normalize_query->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type'); + $normalize_query->condition($this->conditions); } - // Calculate maximum keyword relevance, to normalize it. - $first->addExpression('SUM(i.score * t.count)', 'calculated_score'); - $this->normalize = $first + // The normalization factor is the total of all search scores. + $normalize_query->addExpression('SUM(i.score * t.count)', 'calculated_score'); + $this->normalize = $normalize_query ->range(0, 1) ->orderBy('calculated_score', 'DESC') ->execute() @@ -419,13 +417,12 @@ /** * Executes the search. * - * If not already done, this executes the first pass query. Then the complex - * conditions are applied to the query including score expressions and - * ordering. - * - * @return boolean - * FALSE if the first pass query returned no results, and a database result - * set if there were results. + * If not already done, this prepares and normalizes the query. Then the + * complex conditions are applied to the query including score expressions + * and ordering. + * + * @return + * A query result set containing the results of the search query. */ public function execute() { if (!$this->executedPrepare) { @@ -490,7 +487,7 @@ // Clone the inner query. $inner = clone $this->query; - // Add conditions to query. + // Add conditions to the query. $inner->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type'); $inner->condition($this->conditions); @@ -501,7 +498,7 @@ $expressions =& $inner->getExpressions(); $expressions = array(); - // Add the sid as the only field and count them as a subquery. + // Add sid as the only field and count them as a subquery. $count = db_select($inner->fields('i', array('sid')), NULL, array('target' => 'slave')); // Add the COUNT() expression.