Community Documentation

do_search

5 search.module do_search($keywords, $type, $join1 = '', $where1 = '1', $arguments1 = array(), $select2 = 'i.relevance AS score', $join2 = '', $arguments2 = array(), $sort_parameters = 'ORDER BY score DESC')
6 search.module do_search($keywords, $type, $join1 = '', $where1 = '1 = 1', $arguments1 = array(), $columns2 = 'i.relevance AS score', $join2 = '', $arguments2 = array(), $sort_parameters = 'ORDER BY score DESC')

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()).

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 negative or phrase matches)

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.

$columns2: (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 objects for the search results.

Related topics

▾ 2 functions call do_search()

hook_search in developer/hooks/core.php
Define a custom search routine.
node_search in modules/node/node.module
Implementation of hook_search().

File

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

Code

<?php
function do_search($keywords, $type, $join1 = '', $where1 = '1 = 1', $arguments1 = array(), $columns2 = '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[6]) {
    if ($query[6] == 'or') {
      drupal_set_message(t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.'));
    }
  }
  if ($query === NULL || $query[0] == '' || $query[2] == '') {
    return array();
  }

  // Build query for keyword normalization.
  $conditions = "$where1 AND ($query[2]) AND i.type = '%s'";
  $arguments1 = array_merge($arguments1, $query[3], array($type));
  $join = "INNER JOIN {search_total} t ON i.word = t.word $join1";
  if (!$query[5]) {
    $conditions .= " AND ($query[0])";
    $arguments1 = array_merge($arguments1, $query[1]);
    $join .= " INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type";
  }

  // Calculate maximum keyword relevance, to normalize it.
  $select = "SELECT SUM(i.score * t.count) AS score FROM {search_index} i $join WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d ORDER BY score DESC";
  $arguments = array_merge($arguments1, array($query[4]));
  $normalize = db_result(db_query_range($select, $arguments, 0, 1));
  if (!$normalize) {
    return array();
  }
  $columns2 = str_replace('i.relevance', '(' . (1.0 / $normalize) . ' * SUM(i.score * t.count))', $columns2);

  // Build query to retrieve results.
  $select = "SELECT i.type, i.sid, $columns2 FROM {search_index} i $join $join2 WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d";
  $count_select =  "SELECT COUNT(*) FROM ($select) n1";
  $arguments = array_merge($arguments2, $arguments1, array($query[4]));

  // Do actual search query
  $result = pager_query("$select $sort_parameters", 10, 0, $count_select, $arguments);
  $results = array();
  while ($item = db_fetch_object($result)) {
    $results[] = $item;
  }
  return $results;
}
?>

Comments

Utilizing the return value of do_search

I believe the documentation on this function to be poor, and have filed a bug report. For people who are having trouble utilizing the return value of do_search, please see http://drupal.org/node/993834

Here is a small piece of example code on utilizing do_search():

<?php
$searchResults
= do_search($searchString, "node");
foreach(
$searchResults as $result)
{
  
//the 'sid' is actually a node id.
  
$nid = $result->sid;
  
  
//do whatever you want with the node ID
}
?>

It also appears that the search text snippet (the text you see under the node title when searching using Drupals search form) is in the 'search_dataset table' keyed by the 'sid' you get from do_search().

Hard-coded 10 Results returned

This function will only every return at most 10 results. This is due to the hard-coding of 10 as the limit in the pager_query (near bottom -2nd parameter). In order to have a search function which returns more then 10 or *gasp* all results:

1. Create your own module with a custom search function.
2. Copy the code from do_search into your custom search function.
3. Add a $limit parameter with default 10 to the function parameters
4. Then replace 10 with $limit in the pager_query.

If you want all results returned (for example, when implementing a web-service) simply replace
$result = pager_query("$select $sort_parameters", 10, 0, $count_select, $arguments);
with
$result = db_query("$select $sort_parameters", $arguments);
in your custom search function.

Login or register to post comments