Búsqueda instantánea con AJAX

Volvemos nuevamente al tema de consultas en MySQL, haciendo uso de AJAX y PHP. En esta oportunidad veremos una busqueda instantánea. Quizás ha notado que algunos blogs tienen su sistema de busqueda de entradas(posts) y que los resultados de la busqueda se cargan en otra página. Aunque existen otros que los resultados aparecen en la misma página haciendo uso de AJAX. Pues bien eso es lo vamos a ver ahora.

Hay que tener en cuenta debemos hacer algunos cambios a nuestra base de datos. ¿Porqué? Cuando buscamos un sólo término o palabra no existe problema, podemos hacer uso de la sentencia SELECT ... LIKE contenido='termino' OR titulo='termino'.

Pero, ahora supongamos que queremos buscar una expresión, entonces se deberá buscar si el titulo o contenido del post lo contiene. En ese caso no haremos en trabajo con un simple LIKE debemos hacer algo mas.

Bien entonces empezemos...

Vamos definir los campos de la tabla, la cual usaremos para este ejemplo.

CREATE TABLE `post` (
`idpost` INT( 7 ) NOT NULL auto_increment ,
`titulo` VARCHAR( 70 ) NOT NULL ,
`contenido` TEXT NOT NULL ,
`autor` VARCHAR( 20 ) NOT NULL,
KEY `idpost` (`idpost`)
) TYPE = MYISAM ;

Bien ahora debemos de crear un índice FULLTEXT, que es útil para el segundo caso explicado, cuando buscamos expresiones o conjuntos de palabras en una tabla. Lo realizamos de la siguiente manera:

ALTER TABLE post ADD FULLTEXT(titulo, contenido); 

De esta manera cuando realicemos una busqueda, se trabajará en los dos campos que expecificamos dentro del FULLTEXT. Pero la instrucción de busqueda no será como con el LIKE, sino de la siguiente manera:

SELECT * FROM post WHERE MATCH(titulo, contenido) AGAINST ('$terminos) 

La función MATCH  ...  AGAINST ... , es usado en consultas en lenguaje natural parecido a como lo hacen los motores de búsqueda.

Nota: La funciónn MATCH ... AGAINST ... falla a veces cuando la expresión a buscar tiene solo una palabra. Para la busqueda de una sola palabra hacemos uso de LIKE.

Ahora a nuestra aplicación ...

Vamos a definir los archivos que realizará el proceso:

  • conexion.php >> Datos de la conexión a la base de datos.
  • funciones.js >> El objeto XMLHttpRequest que usaremos y otras funciones en JavaScript.
  • index.php >> El archivo principal que contendrá el formulario de busqueda.
  • busqueda.php >> Realizará la busqueda en si, seleccionará la busqueda adecuada a la expresion ingresada.

conexion.php

Este archivo contiene los datos de la conexión. Recuerde cambiar los datos por los suyos si desea probarlos en su PC.

<?php 
   $bd_host = "localhost"; 
   $bd_usuario = "root"; 
   $bd_password = ""; 
   $bd_base = "ribosomatic"; 
   $con = mysql_connect($bd_host, $bd_usuario, $bd_password); 
   mysql_select_db($bd_base, $con); 
?>

funciones.js

Aquí se encuentran las funciones para llamar el objeto XMLHttpRequest y llamar al proceso de busqueda.

function nuevoAjax(){
	var xmlhttp=false;
 	try{
		xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
	}catch(e){
		try {
			xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		}catch(E){
 			xmlhttp = false;
 		}
 	}
	
	if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
		xmlhttp = new XMLHttpRequest();
	}
   
	return xmlhttp;
}

function buscarDato(){
	resul = document.getElementById('resultado');
	bus=document.frmbusqueda.dato.value;
   
	ajax=nuevoAjax();
	ajax.open("POST", "busqueda.php",true);
	ajax.onreadystatechange=function() {
		if (ajax.readyState==4) {
			resul.innerHTML = ajax.responseText
		}
	}
	ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	ajax.send("busqueda="+bus)
}

index.php

Definimos el archivo JavaScript que usará la página, es este caso funciones.js. Tambien definimos los estilos. En el evento onsubmit del formulario definimos la función JavaScript que llamará al proceso de busqueda.

<html>
	<head>
   	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
   	<title>Untitled Document</title>
   	<script type="text/javascript" src="funciones.js"></script>
   	<style type="text/css">
		legend {
			font-family: Verdana, Arial, Helvetica, sans-serif;
			font-weight: bold;
			font-size: 12px;
		}
		.titulo{
			width:20%;
		}
		.contenido{
			width:60%;
		}
		.autor{
			width:15%;
		}
		</style>
	</head>
  <body>
    <form name="frmbusqueda" action="" onsubmit="buscarDato(); return false">
    <div align="center">Termino a buscar:
    <input type="text" name="dato" /> 
    </div>
    </form>
    <fieldset><legend>Resultado</legend>
    <div id="resultado"></div>
    </fieldset>
  </body>
</html>

busqueda.php

Este es el archivo principal, dependiendo del término o expresiones ingresadas buscará haciendo uso de un simple LIKE o MATCH ... AGAINST.

<?php
   require('conexion.php');
   $busqueda=$_POST['busqueda'];
   if ($busqueda<>''){
   	//numero de palabras
   	$trozos=explode(" ",$busqueda);
   	$numero=count($trozos);
   	if ($numero==1) {
   		$cadbusca="SELECT * FROM post WHERE CONTENIDO LIKE '%$busqueda%' OR TITULO LIKE '%$busqueda%' LIMIT 10;";
   	} elseif ($numero>1) {
   		$cadbusca="SELECT * , MATCH ( TITULO, CONTENIDO ) AGAINST ( '$busqueda' ) AS Score FROM post WHERE MATCH ( TITULO, CONTENIDO ) AGAINST ( '$busqueda' ) ORDER BY Score DESC LIMIT 50;";
   	}
   
   	function limitarPalabras($cadena, $longitud, $elipsis = "..."){
   	$palabras = explode(' ', $cadena);
   	if (count($palabras) > $longitud)
   		return implode(' ', array_slice($palabras, 0, $longitud)) . $elipsis;
   	else
   	return $cadena;
   	}
?>
<table border="1px">
<tbody>
	<tr>
	<td class="titulo">Titulo</td>
	<td class="contenido">Contenido</td>
	<td class="autor">Autor</td>
	</tr>
<?php
   	$result=mysql_query($cadbusca, $con);
   	$i=1;
   	while ($row = mysql_fetch_array($result)){
	   echo "
	   <tr>
	   <td class="titulo">".$row['titulo']."</td>
	   <td class="contenido">".limitarPalabras($row['contenido'],20)."</td>
	   <td class="autor">".$row['autor']."</td>
	   </tr>";
	   $i++;
   	}
?>
</tbody>
</table>
<?php
//cierra el if inicial
}
?> 

Esta es una forma de combinar AJAX con proceso un poco mas avanzados de PHP y consultas MySQL. Pueden descargar el código, y el ejemplo más visible es nuestro propio sistema de búsqueda, por supuesto, mejorado y con algunas características extras.

Comentarios

  1. avatar Aprendiz 2009-06-24 19:38:07 12 buen ejemplo.
  2. avatar Salvador 2009-03-06 12:54:36 11 Funciona perfectamente bien, muchas gracias...
  3. avatar jesusvld 2008-09-20 08:01:42 10 ¿Te asegurado de crear un índice FULLTEXT para las 2 columnas (contenido, titulo)?

    En la sección /ejemplos tambien me da error. Voy a revisar eso.
  4. avatar dante 2008-09-20 00:47:55 9 cuando busco dos terminos me sale asi

    Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in C:\AppServ\www\carpeta\busqueda.php on line 37
  5. avatar GabrielLawana 2007-11-08 17:14:04 8 what is freaking blog about http://facebook-proxy-vpn.blogspot.com
    i understand that is for anonymous surfing people use it for http://facebook.com http://myspace.com other social networking sites
    like http://360.yahoo.com how can i use it for torrent or eDonkey.
  6. avatar milardovich 2007-10-05 16:55:10 7 Jesus, muy lindo el articulo <img style="border:0px;" src="/img/caritas/risueno.gif" alt="risas" title="Risas" width="18" height="18" />, hay uno parecido pero sin ajax en desarrollo web:
    http://www.desarrolloweb.com/articulos/2087.php
    ;) salu2!
  7. avatar jesusvld 2007-05-25 18:06:49 6 hola pablo trata de separa un las etiquetas < > para entender mejor lo que quieres decir.
  8. avatar pablo 2007-05-25 12:27:40 5 perdon, se cortó ,ahora sigo:
    aqui mando la info del textobox y del radio button
    ajax.send("busqueda=" bus "
  9. avatar pablo 2007-05-25 12:11:57 4 hola. estoy ocupando tu codigo en un buscador de libros, en cuya base de datos esta el dcodigo del libro (un numero de 5 digitos), el titulo y el autor. me interesa que lagente pueda buscar tanto por codigo , titulo autor. para esto puse bajo el textbox de busqueda tres radiobuttons, asi el codifo del formulario queda:
    < code >
    < form name="frmbusqueda" action="" onsubmit="buscarDato(); return false" >
    < div align="center" >

    < input type="text" name="dato" / >
    < br / >

    < input type="radio" name="eleccion" value="1" > Codigo
    < input type="radio" name="eleccion" value="2" > Titulo
    < input type="radio" name="eleccion" value="3" > Autor


    < /div >
    < /form >



    < fieldset >< legend >Resultado< /legend >
    < div id="resultado" >< /div >
    < /fieldset >
    < /code >

    en funciones.js cambie por lo siguiente:

    function buscarDato(){
    resul = document.getElementById('resultado');

    bus=document.frmbusqueda.dato.value;
    //aca esta el campo de los radiobuttons
    elect=document.frmbusqueda.eleccion.value;
    ajax=nuevoAjax();
    ajax.open("POST", "busqueda.php",true);
    ajax.onreadystatechange=function() {
    if (ajax.readyState==4) {
    resul.innerHTML = ajax.responseText
    }
    }
    ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

    //aqui los mando
    ajax.send("busqueda=" bus "
  10. avatar jesusvld 2006-11-11 17:33:31 3 Hola Battousai, cerrar la conexión dependerá del numero de peticiones a la base de datos mysql y por ende al servidor que lo contiene. Si por ejemplo la colocas en un servidor web y tu pagina recibe muchas visitas que generan constantes sentencias mysql, entonces es necesario usar la instruccion mysql_close(), es una buena practica; pero el ejemplo era instructivo e iba de frente al grano en lo que respecta a Ajax. Pero repito, es una buen practica cerrar la conexión. Saludos <img style="border:0px;" src="/img/caritas/risueno.gif" alt="risas" title="Risas" width="18" height="18" />

Dejar un comentario