Cita:
Iniciado por ocp001a Podrías intentar probando la distancia levenshtin, o con las funciones soundex o similar text. [url]http://php.net/manual/es/function.levenshtein.php[/url]
nose si alguien habrá seguido el post pero bueh...
comenzamos con el código
gracias a ocp001a y su aporte me puse a investigar un poco, la verdad no esperaba tan buenos resultados (toca filtrar un poco) ya que en cierta forma otorga bastantes resultados basuras...
en si el código esta "vivo" y lo he testeado "un poco", no se rían de mi forma de programar, comenten de forma constructiva!
basta de blablas... a ver un poco de source!
la librería "class.php", es algo un poco "primitiva" aunque indexa correctamente (en varios casos mejor que like y against), decidí meterlo todo dentro de una clase para que fuese un poco mas ordenada, la función "install" la puse simplemente porque existe quienes no saben como subir un .sql
nota: la librería mysql "tradicional" fue declarada deprecada, creo que algunos no están muy familiarizados con las librerías mysqli o PDO por tal causa decidí usar la librería tradicional, simplemente para que todos puedan seguir el hilo
Código PHP:
<?php
class index
{
private $mysqlr;
//la clase constructora
public function __construct($host, $user, $pass, $db)
{
//creamos una conexion y almacenamos el identificador
$this->mysqlr = mysql_connect($host, $user, $pass) or die(mysql_error());
//cambiamos la encodificacion a utf8
mysql_query('SET NAMES utf8') or die(mysql_error());
//seleccionamos la base de datos
mysql_select_db($db) or die(mysql_error());
}
public function __desctruct()
{
//desconectamos el mysql
mysql_close($this->mysqlr);
}
public function save($txt, $minLen = 2)
{
// prevenir las llamadas sin conexion
if(!isset($this)){ return false; }
//multibite en utf8
mb_internal_encoding("UTF-8");
//remplasar delimitadores por un espacio
$txt = str_replace(array(".", '"', "'", ',', ':', ';', '@', '/', '\\', "\n", "\r", "\t", "[", "]", "(", ")") , ' ', $txt);
//convertir la cadena de texto en una matris
$txt = explode(' ', $txt);
$values = '';
//recorrer cada palabra y agregarla al index
foreach($txt as $keyword)
{
//comprobar que supera la longitud minina
if(mb_strlen($keyword) >= $minLen)
{
$values .= ($values != '' ? ', ' : '')."('$keyword')";
}
}
//echo "INSERT IGNORE INTO `lib_post_index` (`key`) VALUES $values";
if($values != '')
{
mysql_query("INSERT IGNORE INTO `lib_post_index` (`key`) VALUES $values", $this->mysqlr) or die(mysql_error());
}
}
public function check($key, $sens = 2)
{
// prevenir las llamadas sin conexion
if(!isset($this)){ return false; }
if($query = mysql_query("SELECT *, levenshtein('$key', `key`) AS `lvs` FROM `lib_post_index` WHERE levenshtein('$key', `key`) BETWEEN 0 AND $sens ORDER BY `lvs`, `key` ASC"))
{
return $query;
}
}
public function install()
{
// prevenir las llamadas sin conexion
if(!isset($this)){ return false; }
//comprobar que la funcion no exista y luego instalar;
$result = mysql_query("SHOW FUNCTION STATUS LIKE 'levenshtein'") or die(mysql_error());
if(mysql_num_rows($result) == 0)
{
mysql_query("CREATE FUNCTION levenshtein( s1 VARCHAR(255), s2 VARCHAR(255) )
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
DECLARE s1_char CHAR;
-- max strlen=255
DECLARE cv0, cv1 VARBINARY(256);
SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0;
IF s1 = s2 THEN
RETURN 0;
ELSEIF s1_len = 0 THEN
RETURN s2_len;
ELSEIF s2_len = 0 THEN
RETURN s1_len;
ELSE
WHILE j <= s2_len DO
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
END WHILE;
WHILE i <= s1_len DO
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
WHILE j <= s2_len DO
SET c = c + 1;
IF s1_char = SUBSTRING(s2, j, 1) THEN
SET cost = 0; ELSE SET cost = 1;
END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
IF c > c_temp THEN SET c = c_temp; END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
IF c > c_temp THEN
SET c = c_temp;
END IF;
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
END WHILE;
SET cv1 = cv0, i = i + 1;
END WHILE;
END IF;
RETURN c;
END;") or die(mysql_error());
mysql_query("CREATE FUNCTION levenshtein_ratio( s1 VARCHAR(255), s2 VARCHAR(255) )
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE s1_len, s2_len, max_len INT;
SET s1_len = LENGTH(s1), s2_len = LENGTH(s2);
IF s1_len > s2_len THEN
SET max_len = s1_len;
ELSE
SET max_len = s2_len;
END IF;
RETURN ROUND((1 - LEVENSHTEIN(s1, s2) / max_len) * 100);
END;") or die(mysql_error());
mysql_query("CREATE TABLE IF NOT EXISTS `lib_post_index` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`key` varchar(255) DEFAULT NULL,
`parents` text CHARACTER SET ascii,
PRIMARY KEY (`id`),
UNIQUE KEY `key` (`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1") or die(mysql_error());
}
}
}
?>
fuente "function levenshtein" -> http://stackoverflow.com/questions/4671378/levenshtein-mysql-php
dentro de todo allí esta lo mas importante, la función levenshtein ella retornara los elementos que contengan mas cercanía a la palabra clave
la función save "parsea" el texto según los delimitadores indicados y retorna un array, el loop genera la query y el mysql_query los guarda en la tabla "lib_post_index"
en si es todo esta bastante fácil de entender creo...
index.php esta es una interface muy precaria pero para testear sobra
Código PHP:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<?php
//incluimos la clase principal
include 'class.php';
//creamos el objeto
$index = new index('localhost', 'usuario mysql', 'password mysql', 'base de datos');
//comprobamos que alla datos suficientes como para guardar el string
if(isset($_POST['string']) && strlen($_POST['string']) > 2)
{
//creamos el index
$index->save($_POST['string']);
}
// comprobamos si hay una keyword
if(isset($_POST['keyword']))
{
//generamos una consulta
$query = $index->check($_POST['keyword'], 2);
//imprimimos el/los resultado(s)
while($_result = mysql_fetch_assoc($query))
{
print_r($_result);
echo '<br />';
}
}
?>
<body>
<form method="post" enctype="multipart/form-data">
buscar en el index<br />
<input name="keyword" type="text" value="<?php echo $_POST['keyword']; ?>" /><br /><br />
indexar texto<br />
<textarea name="string"></textarea><br />
<input type="submit" />
</form>
</body>
</html>
comenten cualquier idea o algo que se les ocurra para optimizar el codigo, "maten a los que den copy&past"
haha