Same name and namespace in other branches
  1. 4.6.x modules/search.module \do_search()
  2. 4.7.x modules/search.module \do_search()
  3. 6.x modules/search/search.module \do_search()

Do a query on the full-text search index for a word or words.

This function is normally only called by each module that support the indexed search (and thus, implements hook_update_index()).

Two queries are performed which can be extended by the caller.

The first query selects a set of possible matches based on the search index and any extra given restrictions. This is the classic "OR" search.

SELECT i.type, i.sid, SUM(i.score*t.count) AS relevance FROM {search_index} i INNER JOIN {search_total} t ON i.word = t.word $join1 WHERE $where1 AND (...) GROUP BY i.type, i.sid

The second query further refines this set by verifying advanced text conditions (such as AND, negative or phrase matches), and orders the results on a the column or expression 'score':

SELECT i.type, i.sid, $select2 FROM temp_search_sids i INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type $join2 WHERE (...) ORDER BY score DESC

Parameters

$keywords: A search string as entered by the user.

$type: A string identifying the calling module.

$join1: (optional) Inserted into the JOIN part of the first SQL query. For example "INNER JOIN {node} n ON n.nid = i.sid".

$where1: (optional) Inserted into the WHERE part of the first SQL query. For example "(n.status > %d)".

$arguments1: (optional) Extra SQL arguments belonging to the first query.

$select2: (optional) Inserted into the SELECT pat of the second query. Must contain a column selected as 'score'. defaults to 'i.relevance AS score'

$join2: (optional) Inserted into the JOIN par of the second SQL query. For example "INNER JOIN {node_comment_statistics} n ON n.nid = i.sid"

$arguments2: (optional) Extra SQL arguments belonging to the second query parameter.

$sort_parameters: (optional) SQL arguments for sorting the final results. Default: 'ORDER BY score DESC'

Return value

An array of SIDs for the search results.

Related topics

File

modules/search/search.module, line 837
Enables site-wide keyword searching.

Code

function do_search($keywords, $type, $join1 = '', $where1 = '1', $arguments1 = array(), $select2 = 'i.relevance AS score', $join2 = '', $arguments2 = array(), $sort_parameters = 'ORDER BY score DESC') {
  $query = search_parse_query($keywords);
  if ($query[2] == '') {
    form_set_error('keys', t('You must include at least one positive keyword with @count characters or more.', array(
      '@count' => variable_get('minimum_word_size', 3),
    )));
  }
  if ($query === NULL || $query[0] == '' || $query[2] == '') {
    return array();
  }

  // First pass: select all possible matching sids, doing a simple index-based OR matching on the keywords.
  // 'matches' is used to reject those items that cannot possibly match the query.
  $conditions = $where1 . ' AND (' . $query[2] . ") AND i.type = '%s'";
  $arguments = array_merge($arguments1, $query[3], array(
    $type,
    $query[4],
  ));
  $result = db_query_temporary("SELECT i.type, i.sid, SUM(i.score * t.count) AS relevance, COUNT(*) AS matches FROM {search_index} i INNER JOIN {search_total} t ON i.word = t.word {$join1} WHERE {$conditions} GROUP BY i.type, i.sid HAVING COUNT(*) >= %d", $arguments, 'temp_search_sids');

  // Calculate maximum relevance, to normalize it
  $normalize = db_result(db_query('SELECT MAX(relevance) FROM temp_search_sids'));
  if (!$normalize) {
    return array();
  }
  $select2 = str_replace('i.relevance', '(' . 1.0 / $normalize . ' * i.relevance)', $select2);

  // Second pass: only keep items that match the complicated keywords conditions (phrase search, negative keywords, ...)
  $conditions = '(' . $query[0] . ')';
  $arguments = array_merge($arguments2, $query[1]);
  $result = db_query_temporary("SELECT i.type, i.sid, {$select2} FROM temp_search_sids i INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type {$join2} WHERE {$conditions} {$sort_parameters}", $arguments, 'temp_search_results');
  if (($count = db_result(db_query('SELECT COUNT(*) FROM temp_search_results'))) == 0) {
    return array();
  }
  $count_query = "SELECT {$count}";

  // Do actual search query
  $result = pager_query("SELECT * FROM temp_search_results", 10, 0, $count_query);
  $results = array();
  while ($item = db_fetch_object($result)) {
    $results[] = $item;
  }
  return $results;
}