HomeMySQL Page 2 - Using Boolean Operators for Full Text and Boolean Searches with MySQL
Reintroducing some earlier concepts - MySQL
Implementing full text searches with MySQL can improve the execution of queries against specific database tables. If you want to put this useful feature to work for you, start reading this article now! Welcome to the final tutorial of the series that began with "Performing Full Text and Boolean Searches with MySQL." Made up of three tutorials, this series walks you through the basics of creating full text indexes in MySQL tables, and shows you how to take advantage of Boolean searches to improve the performance of your SQL queries.
An excellent starting point consists of using the same search engine that I built in the first article of the series, incorporating the sample "USERS" database table created specifically in that occasion.
So let me remind you quickly of the set of simple SQL statements that create the database table in question:
CREATE TABLE users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL, firstname VARCHAR(64), lastname VARCHAR(64), email VARCHAR(64) comments TEXT FULLTEXT(firstname,lastname,comments) );
As you'll certainly recall, the previous database table was defined in such a way that it incorporates three fields as full-text indexes, called "firstname," "lastname" and "comment" respectively.
So far, so good, right? Having created the prior database table, it's time to fill it in with some basic records, as indicated below:
("users" database table)
Id firstname lastname email comments
1 Alejandro Gervasio alejandro@domain.com MySQL is great for building a search engine 2 John 'Williams john@domain.com PHP is a server side scripting language 3 Susan Norton susan@domain.com JavaScript is good to manipulate documents 4 Julie Wilson julie@domain.com MySQL is the best open source database server
And finally, here are the signatures that correspond to the two source files that comprise the MySQL-based search engine utilized in the preceding articles of the series:
<?php // define 'MySQL' class class MySQL{ private $conId; private $host; private $user; private $password; private $database; private $result; const OPTIONS=4; public function __construct($options=array()){ if(count($options)!=self::OPTIONS){ throw new Exception('Invalid number of connection parameters'); } foreach($options as $parameter=>$value){ if(!$value){ throw new Exception('Invalid parameter '.$parameter); } $this->{$parameter}=$value; } $this->connectDB(); } // connect to MySQL private function connectDB(){ if(!$this->conId=mysql_connect($this->host,$this- >user,$this->password)){ throw new Exception('Error connecting to the server'); } if(!mysql_select_db($this->database,$this->conId)){ throw new Exception('Error selecting database'); } } // run query public function query($query){ if(!$this->result=mysql_query($query,$this->conId)){ throw new Exception('Error performing query '.$query); } return new Result($this,$this->result); } public function escapeString($value){ return mysql_escape_string($value); } } // define 'Result' class class Result { private $mysql; private $result; public function __construct($mysql,$result){ $this->mysql=$mysql; $this->result=$result; } // fetch row public function fetchRow(){ return mysql_fetch_assoc($this->result); } // count rows public function countRows(){ if(!$rows=mysql_num_rows($this->result)){ return false; } return $rows; } // count affected rows public function countAffectedRows(){ if(!$rows=mysql_affected_rows($this->mysql->conId)){ throw new Exception('Error counting affected rows'); } return $rows; } // get ID form last-inserted row public function getInsertID(){ if(!$id=mysql_insert_id($this->mysql->conId)){ throw new Exception('Error getting ID'); } return $id; } // seek row public function seekRow($row=0){ if(!is_int($row)||$row<0){ throw new Exception('Invalid result set offset'); } if(!mysql_data_seek($this->result,$row)){ throw new Exception('Error seeking data'); } } } try{ // connect to MySQL $db=new MySQL(array('host'=>'host','user'=>'user','password'=>'password', 'database'=>'database')); $searchterm=$db->escapeString($_GET['searchterm']); $result=$db->query("SELECT firstname, MATCH (firstname,lastname,comments) AGAINST('$searchterm') AS relevance FROM users"); if(!$result->countRows()){ echo 'No results were found.'; } else{ echo '<h2>Users returned are the following:</h2>'; while($row=$result->fetchRow()){ echo '<p>Name: '.$row['firstname'].' Relevance: '.$row ['relevance'].'</p>'; } } } catch(Exception $e){ echo $e->getMessage(); exit(); } ?>
As illustrated above, the search engine is composed of only two source files. The first file is responsible for displaying a common web form for entering different search strings, while the second one is tasked with returning the corresponding result sets according to the search words typed into the referenced online form.
In this case, you can see that I set up a SELECT query by using the already familiar MATCH and AGAINST commands for returning a specific relevance ranking. Thus, based on this context, and providing that the pertinent web form has been filled in with the search term "Alejandro," the results returned by MySQL would be as follows:
/*
Users returned are the following:
Name: Alejandro Relevance: 1.0167628961849
Name: John Relevance: 0
Name: Susan Relevance: 0
Name: Julie Relevance 0
*/
Quite simple, right? Logically, at this point I'm assuming that you're already familiar with working with relevance values, since the topic was treated deeply in the previous article, so in theory you shouldn't have major problems understanding how the above example works.
Okay, now that you hopefully recalled all of the steps required to return relevance rankings from a specific MySQL database table, let's move forward and see how to build queries that accept Boolean operators for performing more advanced searches.
To learn more on this interesting topic, please click on the link that appears below and keep reading.