Re: searching and sorting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> I agree. That is a wise statement, and I have tried to do this with
> regular
> expressions but this doesn't deal with relevance at all, or is there
> something that I am missing? I suppose I could do multiple searches on my
> data to look for "sports cars" first, "cars" second, and "sports" last.
> Then
> I could deal with the separate issue of the text files.

Your database may provide a "full text" search system you can use, which
would be Good in terms of performance, but probably Bad in terms of
portability.

If you need portability, something like this:

<?php
  $words = split('/\\s/', $_POST['search']);

  //Ignore multiple inputs of same word:
  $words = array_flip(array_flip($words));

  $query = " select fields, you, need, ";
  //This is for real:
  $query .= " (description like '%$search%') ";
  reset($words);
  while (list(, $word) = each($words)){
    $query .= " + (description like '%$word%') ";
  }
  $query .= " as score, ";
  //This is just for debugging, so you can see where points are garnered:
  $query .= " (description like '%$search%') as perfect, ";
  reset($words);
  while (list(, $word) = each($words)){
    $query .= " (description like '%$word%') as 'word_$word', ";
  }
  $query .= " 'filler' "; // Just for the extra comma at the end of the loop
  $query .= " from whatever ";
  $query .= " order by score desc ";

  $matches = mysql_query($query) or trigger_error(mysql_error() . "
$query", E_USER_ERROR);
  while ($row = mysql_fetch_array($matches)){
    list($fields, $you, $want, $score) = $row;
    //For debugging only:
    echo "Scoring<br />\n";
    echo "Perfect: $row[perfect]<br />\n";
    reset($row);
    for ($i = 0; $i < 4; $i++) each($row); //Ignore stuff we already printed
    for ($i = 4; $i < count($row); $i++){
      list($word, $points) = each($row);
      echo "Word match ($word): $points<br />\n";
    }
  }
?>

You'll need to convince MySQL to convert boolean to 0/1.

You can also apply scaling factors so that a perfect match gets, say, 10
points, intead of just 1:
$query .= " 10 * (description like '%$search%') as perfect ";

This is crude, but effective, and can easily be ported to any SQL engine
-- Except, of course, for the data-type conversion from a boolean result
to int, which you need to tweak, but that should be fairly easy to work
out a hack for all SQL engines, perhaps by using a variable function name:

$query .= " 10 * $sql_bool_to_int(description like '%$search%') as perfect ";

You then define $sql_bool_to_int for each SQL engine you need, and Bob's
your uncle.

-- 
Like Music?
http://l-i-e.com/artists.htm

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux