2011-08-29 21 views
7

Estoy intentando crear un motor de búsqueda para un sitio basado en inventario. El problema es que tengo información dentro de bbtags (como en [b]test[/b] sentence, el test debe estar valorado en 3, mientras que sentence se debe valorar en 1).Consultas de búsqueda de PHP mysql

Aquí es un ejemplo de un índice:
My test sentence, my my (tiene un SKU de TST-DFS)
La Base de datos:

|Product| word |relevancy| 
| 1 | my | 3 | 
| 1 | test | 1 | 
| 1 |sentence| 1 | 
| 1 | TST-DFS| 10 | 

Pero ¿cómo iba a coincidir con TST-DFS si el usuario escribió en TST DFS? Me gustaría que la SKU para tener una relevancia de 8 decir, en lugar de la plena 10 ..

He oído que la función de búsqueda de texto completo en MySQL ayudaría, pero me parece que no puede encontrar una buena manera de hazlo. Me gustaría evitar cosas como SINDICATOS y mantener la consulta lo más optimizada posible.

Cualquier ayuda para crear un buen sistema para esto sería genial.

Gracias, Max

+0

¿No puedes usar 'capacidades FULLTEXT' de MySQL, o es que lo que quiere decir cuando se dice "índice"? – Bojangles

+0

El problema es que tengo mucha información que es importante, pero FULLTEXT de MySQL no sabe que es importante (como números de sku, nombre de producto y otras palabras determinadas). Así que estoy indexando cada palabra en cada producto, y no creo que FULLTEXT de MySQL me ayude a buscar en cada una de las filas. – Ben

+0

Oh, claro. Por lo que puedo ver, no, 'FULLTEXT' no sería útil en absoluto. Una pena realmente, ya que es una parte maravillosa de MySQL. – Bojangles

Respuesta

5

Pero, ¿cómo podría coincidir con TST-DFS si el usuario escribe en TST DFS?
me gustaría que SKU para tener una relevancia de 8 dicen que, en lugar de la totalidad de 10 ..

Si tengo la pregunta correcta, la respuesta es fácil.
Bueno, si forje su consulta un poco antes de enviarla a mysql.

Ok, digamos que tenemos $query y contiene TST-DFS.

¿Nos vamos a centrar en tramos de palabra? supongo que debería, como la mayoría de los motores de búsqueda hacen, por lo que:

$ok=preg_match_all('#\w+#',$query,$m); 

ahora si ese patrón coincide ... $m[0] contiene la lista de palabras en $query.
Esto se puede ajustar con precisión a su SKU, pero la coincidencia con palabras completas de forma AND es prácticamente lo que el usuario supone que está sucediendo. (como ocurre en google y yahoo)

Luego tenemos que cocinar una expresión $expr que se inyectará en nuestra consulta final.

if(!$ok) { // the search string is non-alphanumeric 
    $expr="false"; 
} else { // the search contains words that are no in $m[0] 
    $expr=''; 
    foreach($m[0] as $word) { 
    if($expr) 
     $expr.=" AND "; // put an AND inbetween "LIKE" subexpressions 
    $s_word=addslashes($word); // I put a s_ to remind me the variable 
           // is safe to include in a SQL statement, that's me 
    $expr.="word LIKE '%$s_word%'"; 
    } 
} 

Ahora $expr debe ser similar "words LIKE '%TST%' AND words LIKE '%DFS%'"

Con ese valor, podemos construir la consulta final:

$s_expr="($expr)"; 
$s_query=addslashes($query); 

$s_fullquery= 
"SELECT (Product,word,if((word LIKE '$s_query'),relevancy,relevancy-2) as relevancy) ". 
"FROM some_index ". 
"WHERE word LIKE '$s_query' OR $s_expr"; 

que queda modificada, para "TST-DFS":

SELECT (Product,word,if((word LIKE 'TST-DFS'),relevancy,relevancy-2) as relevancy) 
FROM some_index 
WHERE word LIKE 'TST-DFS' OR (word LIKE '%TST%' AND word LIKE '%DFS%') 

Como puede ver, en la primera línea SELECT, si la coincidencia es parcial, MySQL volverá relevancia-2

En la tercera, la cláusula WHERE, si el partido completo falla, $s_expr, la consulta coincidencia parcial cocinamos con antelación, se pretende en lugar.

+0

corregido. mi lógica estaba equivocada ** Ahora ** '$ expr' debería verse como' words like '% TST%' AND words LIKE '% DFS%' ' – ZJR

+0

Entonces, ¿dónde está obteniendo la columna' relevancia'? – Ben

+0

sin importar lo anterior, ¿cómo podría funcionar esto con una consulta de varias palabras? Parece que se está comparando con ser la palabra perfectamente o con todas las palabras secundarias, ¿estoy en lo cierto al respecto? – Ben

0

me gustaría añadir una columna que se despojó de todo, faltas de ortografía de carácter especial, y luego upcased (o crear una función que compara el texto que ha sido despojado y upcased). De esa manera, su relevancia será consistente.

2

me gusta a minúsculas todo y tira a caracteres especiales (como en un número de teléfono o tarjeta de crédito me saco todo en ambos lados que no es un número)

1

En lugar de tratar de crear su propia FTS solución, podría tratar de ajustar el motor MySQL FTS a sus requisitos. Lo que he visto hacer es crear una nueva tabla para almacenar sus datos FTS. Cree una columna para cada dato diferente que desee que tenga una relevancia diferente. Para su campo de sku, puede almacenar el sku sin formato, con espacios, guiones bajos, guiones y cualquier otro carácter especial intacto. A continuación, almacene una versión reducida con todos estos elementos eliminados. También es posible que desee almacenar una versión con cero iniciales, ya que las personas a menudo dejan cosas así. Puede almacenar todas estas variaciones en la misma columna. Guarde el nombre de su producto en otra columna y la descripción del producto en otra columna. Crea un índice separado en cada columna. Luego, cuando haces tu búsqueda, puedes buscar cada columna individualmente y multiplicar el rango de los resultados según la importancia que creas que tiene esa columna. Por lo tanto, puede multiplicar los resultados de sku por 10, título por 5 y dejar los resultados de la descripción como están. Es posible que tenga que experimentar un poco para obtener los resultados que desea, pero en última instancia puede ser más simple que crear su propio índice.

+0

Tengo bbcode que rodea los subtítulos en la descripción. ¿podría tomar todo entre los códigos b, y combinar todos los mundos (con espacios entre ellos) en una columna, y multiplicar esa columna por decir 3? Además, ¿podría dar un ejemplo simple de uso de texto completo con diferentes multiplicadores? – Ben

+0

Si estuviera dispuesto a ampliar su respuesta, me complacería agregar una recompensa a esta pregunta. – Ben

1

Crear una tabla de palabras clave. Algo similar a:

integer keywordId (autoincrement) | varchar keyword | int pointValue 

Asigne todas las palabras clave posibles, skus, etc. a esta tabla. Crear otra tabla, un puente post-palabras clave, (suponiendo postId es el identificador que ha asignado en la tabla original) a lo largo de las líneas de:

integer keywordId | integer postId 

Una vez que tenga esto, se puede agregar fácilmente palabras clave para cada puesto como está interesado. Para calcular el valor total de puntos para un puesto determinado, una consulta como la siguiente debe hacer el truco:

SELECT sum(pointValue) FROM keywordPostsBridge kpb 
JOIN keywords k ON k.keywordId = kpb.keywordId 
WHERE kpb.postId = YOUR_INTENDED_POST 
1

Creo que la solución es bastante sencilla a menos que me haya perdido algo.

Básicamente ejecuta dos búsquedas, una es coincidencia exacta, la otra es como coincidencia de correspondencia o expresión regular.

Unir dos conjuntos de resultados juntos, como coincidencia izquierda unir coincidencia exacta. Entonces, por ejemplo:

final_relevancy = (IFNULL(like_relevancy, 0) + IFNULL(exact_relevancy, 0) * 3)/4 

Aunque no probé esto. Solo una idea.

0
/* 
q and q1 - you table 
this query takes too much resources, 
make from it update-query (scheduled task or call it on_save if you develop new system) 
*/ 
SELECT 
     CASE 
       WHEN word NOT REGEXP "^[a-zA-Z]+$" 
        /*many replace with junk characters 
        or create custom function 
        or if you have full db access install his https://launchpad.net/mysql-udf-regexp 
        */ 
       THEN REPLACE(REPLACE(word, '-', ' '), '#', ' ') 
       ELSE word 
     END word , 
     CASE 
       WHEN word NOT REGEXP "^[a-zA-Z]+$" 
       THEN 8 
       ELSE relevancy 
     END   relevancy 
FROM (SELECT 'my' word, 
       3  relevancy 

     UNION 

     SELECT 'test' word, 
       1  relevancy 

     UNION 

     SELECT 'sentence' word, 
       1   relevancy 

     UNION 

     SELECT 'TST-DFS' word, 
       10 relevancy 
     ) 
     q 

UNION 

SELECT * 
FROM (SELECT 'my' word, 
       3  relevancy 

     UNION 

     SELECT 'test' word, 
       1  relevancy 

     UNION 

     SELECT 'sentence' word, 
       1   relevancy 

     UNION 

     SELECT 'TST-DFS' word, 
       10 relevancy 
     ) 
     q1 
0
it is a page coading where query result shows 

**i can not use functions by use them work are more easier** 

<html> 
<head> 
</head> 
<body> 
<?php 
//author S_A_KHAN 
//date 10/02/2013 
$dbcoonect=mysql_connect("127.0.0.1","root"); 
if (!$dbcoonect) 
{ 
die ('unable to connect'.mysqli_error()); 
} 
else 
{ 
echo "connection successfully <br>"; 

} 
$data_base=mysql_select_db("connect",$dbcoonect); 


if ($data_base==FALSE){ 

die ('unable to connect'.mysqli_error($dbcoonect)); 
    } 
else 
    { 
echo "connection successfully done<br>"; 
    ***$SQLString = "select * from user where id= " . $_GET["search"] . ""; 
$QueryResult=mysql_query($SQLString,$dbcoonect);*** 

echo "<table width='100%' border='1'>\n"; 
    echo "<tr><th bgcolor=gray>Id</th><th bgcolor=gray>Name</th></tr>\n"; 
    while (($Row = mysql_fetch_row($QueryResult)) !== FALSE) { 
     echo "<tr><td bgcolor=tan>{$Row[0]}</td>"; 
     echo "<td bgcolor=tan>{$Row[1]}</td></tr>"; 
    } 
} 
?> 

</body> 
</html>